Conversation
…mmunications and Payments modules - Mark Sprint 8D as completed (Admin Portal React migration) - Add Sprint 8E (E2E Tests with Playwright) - Move Communications and Payments to high priority pre-MVP - Update frontend stack from Blazor/MudBlazor to React/Tailwind - Remove bUnit references, focus on Playwright for frontend testing - Update documentation (README, architecture, admin-portal docs)
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughMigração documentada do frontend de Blazor → React/Next.js (React 19, Next.js 15) com Tailwind/Zustand/TanStack Query/NextAuth; inclusão de infra de testes (Playwright E2E, Vitest), libs de suporte de testes, ajustes em CI/CD e ampla adição de testes unitários e e2e. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Browser as Usuário (Browser)
participant NextApp as Next.js App
participant NextAuth as NextAuth.js
participant Keycloak as Keycloak (OIDC)
participant API as Backend API
Browser->>NextApp: requisita rota protegida (/admin/...)
NextApp->>NextAuth: verifica sessão / inicia fluxo auth
NextAuth->>Keycloak: redireciona para OIDC (login)
Keycloak->>Browser: exibe formulário de login
Browser->>Keycloak: submete credenciais
Keycloak->>NextAuth: callback com code
NextAuth->>Keycloak: troca code por tokens
NextAuth->>NextApp: cria sessão (cookie HTTP-only)
NextApp->>API: busca dados autenticados (Fetch/Axios via TanStack Query)
API-->>NextApp: retorna dados protegidos
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
- Add playwright.config.ts for NX workspace - Create E2E test structure: - e2e/customer/ (auth, search) - e2e/provider/ (auth, onboarding, dashboard) - e2e/admin/ (auth, providers, documents) - Add E2E test step to pr-validation.yml (disabled) - Add E2E test step to master-ci-cd.yml (disabled)
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
README.md (1)
107-108:⚠️ Potential issue | 🟡 MinorComentário desatualizado na estrutura do projeto.
A linha 107 ainda identifica o Admin Portal como "Blazor WASM", contradizendo a afirmação do PR de que a migração para React foi concluída no Sprint 8D.
📝 Correção sugerida
├── 📁 src/ # Código fonte da aplicação │ ├── Aspire/ # .NET Aspire AppHost │ ├── Bootstrapper/ # API Service entry point │ ├── Modules/ # Módulos de domínio (DDD) │ ├── Shared/ # Contratos e abstrações │ └── Web/ # Aplicações Web -│ ├── MeAjudaAi.Web.Admin/ # Admin Portal (Blazor WASM) +│ ├── MeAjudaAi.Web.Admin/ # Admin Portal (React + Next.js) │ └── meajudaai-web-customer/ # Customer Web App (Next.js 15)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@README.md` around lines 107 - 108, The README's project tree still labels MeAjudaAi.Web.Admin as "Admin Portal (Blazor WASM)"; update that entry to reflect the completed migration to React (e.g., "Admin Portal (React)") so it matches the Sprint 8D changes and PR description; locate the line referencing the MeAjudaAi.Web.Admin folder in README.md and replace the platform note accordingly.docs/architecture.md (1)
2829-3110:⚠️ Potential issue | 🔴 CriticalRemover ou atualizar 280+ linhas de código Fluxor/Refit/MudBlazor desatualizadas.
Esta seção contém implementação extensiva e detalhada da arquitetura Blazor WebAssembly anterior:
- Linhas 2829-2914 (85 linhas): "Fluxor Pattern - State Management" com
ProvidersState,ProvidersActions,ProvidersReducers,ProvidersEffects- pattern que não existe em React/Zustand- Linhas 2916-3024 (108 linhas): "Refit - Type-Safe HTTP Clients" com interfaces C#
.NET,IProvidersApi,IDocumentsApi- tecnologia que não se aplica a Next.js/React- Linhas 3026-3110 (84 linhas): Componentes MudBlazor (
MudDataGrid,MudCard,MudPagination,MudIcon,MudButton) e configuração Blazor WASMTotal: ~280 linhas de código de arquitetura obsoleta que contradizem diretamente a afirmação de que o Admin Portal foi migrado para React no Sprint 8D.
Se a migração foi concluída, estas seções devem ser:
- Removidas completamente, OU
- Movidas para um arquivo de documentação histórica (ex:
docs/admin-portal/blazor-legacy.md), OU- Substituídas por exemplos equivalentes em React/Zustand/TanStack Query
💡 Alternativas para resolver esta inconsistência
Opção 1 (Recomendada): Mover para documentação histórica
# Criar arquivo de referência histórica mkdir -p docs/admin-portal/legacy mv docs/architecture.md docs/architecture-with-legacy.md # Extrair seções Fluxor/Refit/MudBlazor para docs/admin-portal/legacy/blazor-architecture.mdOpção 2: Substituir por exemplos React equivalentes
Exemplo de State Management com Zustand:
// stores/providersStore.ts import { create } from 'zustand'; interface ProvidersState { providers: ProviderDto[]; isLoading: boolean; error: string | null; loadProviders: () => Promise<void>; } export const useProvidersStore = create<ProvidersState>((set) => ({ providers: [], isLoading: false, error: null, loadProviders: async () => { set({ isLoading: true, error: null }); try { const result = await fetch('/api/providers'); const data = await result.json(); set({ providers: data.items, isLoading: false }); } catch (error) { set({ error: error.message, isLoading: false }); } } }));Exemplo de Data Fetching com TanStack Query:
// hooks/useProviders.ts import { useQuery } from '@tanstack/react-query'; export function useProviders(page = 1, pageSize = 20) { return useQuery({ queryKey: ['providers', page, pageSize], queryFn: async () => { const res = await fetch(`/api/providers?page=${page}&pageSize=${pageSize}`); if (!res.ok) throw new Error('Failed to fetch'); return res.json(); } }); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 2829 - 3110, This section contains ~280 lines of obsolete Blazor/Fluxor/Refit/MudBlazor examples (notably ProvidersState, ProvidersActions, ProvidersReducers, ProvidersEffects, IProvidersApi, IDocumentsApi, IServiceCatalogsApi, MudDataGrid, MudPagination, MudCard, etc.) that conflict with the React/Next.js migration; remove these legacy blocks from docs/architecture.md and either (a) move them into a new historical file (e.g., docs/admin-portal/legacy/blazor-architecture.md) preserving the original content, or (b) replace them with concise React equivalents (e.g., mention Zustand store patterns and TanStack Query hooks plus example filenames like stores/providersStore.ts and hooks/useProviders.ts) so the architecture doc reflects the current Admin Portal tech stack.docs/roadmap.md (1)
36-36:⚠️ Potential issue | 🟡 MinorAtualizar nota sobre migração do Admin Portal.
A nota indica que a migração para React está "planejada para o Sprint 8D", mas o PR afirma que o Sprint 8D foi concluído em 24 de março de 2026. A nota deve refletir o status atual.
📝 Correção sugerida
-> **Razão**: SEO crítico para Customer App, performance inicial, ecosystem maduro, hiring facilitado. +> *Admin Portal migrated to React in Sprint 8D (completed March 24, 2026).* - -**Decisão Estratégica**: Dual Stack (Blazor para Admin, React para Customer)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap.md` at line 36, Atualize a linha que atualmente diz "Admin Portal atualmente em Blazor WASM; migração para React planejada para o Sprint 8D." para refletir que o Sprint 8D foi concluído em 24 de março de 2026; altere o texto para algo como "Admin Portal migrado de Blazor WASM para React durante o Sprint 8D (concluído em 24 de março de 2026)." e garanta que qualquer menção a "planejada" ou "planejada para o Sprint 8D" seja removida ou convertida para status concluído.docs/admin-portal/overview.md (2)
125-202:⚠️ Potential issue | 🟠 MajorExemplos de código Blazor/Razor precisam ser atualizados para React/TSX.
Os exemplos de código ainda mostram sintaxe Blazor/Razor:
- Linha 126:
@attribute [Authorize(Policy = ...)]- Linhas 128-136:
<AuthorizeView>,<MudButton>,<MudText>- Linhas 147-151:
@inject LocalizationService,<MudButton>,<MudText>- Linhas 192-201:
DialogService.ShowMessageBox(Blazor API)Se o Admin Portal foi migrado para React (Sprint 8D "CONCLUÍDA"), esses exemplos devem usar React/TSX com componentes correspondentes.
💡 Exemplo de código React equivalente
// Proteção de rota com NextAuth.js import { useSession } from 'next-auth/react'; export default function ProtectedPage() { const { data: session, status } = useSession({ required: true }); if (status === 'loading') return <Spinner />; return ( <div> {session?.user?.role === 'admin' ? ( <Button>Editar</Button> ) : ( <Text>Sem permissão</Text> )} </div> ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 125 - 202, The docs still contain Blazor/Razor examples (AuthorizeView, `@attribute`, `@inject` LocalizationService, MudButton/MudText, DialogService.ShowMessageBox); replace these with React/TSX examples using your app conventions: show a ProtectedPage component using next-auth's useSession (or your auth hook) to gate UI (e.g., ProtectedPage -> const { data: session } = useSession(); session?.user?.role === 'admin' ? <Button>Editar</Button> : <Text>Sem permissão</Text>), replace `@inject` LocalizationService L and L.GetString(...) with your i18n hook (e.g., const { t } = useTranslation(); <Button>{t('Common.Save')}</Button>), and swap DialogService.ShowMessageBox examples for your React dialog API or a window.confirm fallback (e.g., showModal/showConfirm or custom <ConfirmDialog />); update code blocks and explanatory text accordingly so all examples use React/TSX symbols (ProtectedPage, useSession, useTranslation, Button, Text, showModal).
35-102:⚠️ Potential issue | 🟠 MajorAtualizar diagrama e estrutura de diretórios para refletir arquitetura React/Next.js.
O diagrama Mermaid (linhas 37-61) e a estrutura de diretórios (linhas 66-102) ainda descrevem a arquitetura Blazor WebAssembly (Fluxor, .razor files), mas o projeto foi de fato migrado para React/Next.js. A estrutura real contém
app/,components/,hooks/e referencia Next.js/React nopackage.json, confirmando que a migração do Sprint 8D foi concluída.Atualize:
- Diagrama: Remova "Admin Portal (Blazor WASM)", "Fluxor State/Effects", "Refit" e substitua por arquitetura Next.js com React components, Zustand (ou equivalente) e TanStack Query
- Estrutura de diretórios: Remova referências a
.razorfiles eFeatures/Fluxor; reflita a estrutura atual comapp/,(admin)/,components/,hooks/,lib/🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 35 - 102, The docs still describe a Blazor WASM architecture and .razor/Fluxor artifacts; update the Mermaid diagram (replace "Admin Portal (Blazor WASM)" and nodes State, Effects, API labeled as Fluxor/Refit with Next.js/React, Zustand (or equivalent) and TanStack Query and adjust arrows accordingly using the existing node names (UI, State, Effects, API, Gateway, Modules) or renaming UI->ReactComponents and State->Zustand/Store so the flow maps to API Gateway and Backend modules; also replace the directory tree under src/Web/MeAjudaAi.Web.Admin/ to reflect the React/Next.js layout by removing .razor files and the Features/Fluxor folder and adding app/, (admin)/, components/, hooks/, lib/ (keep references to package.json/Next.js where applicable) so the file list and diagram match the Sprint 8D migration.
🧹 Nitpick comments (1)
docs/roadmap-current.md (1)
617-637: Refinar escopo do Sprint 8E - Playwright já está instalado.O Sprint 8E é descrito como "EM ANDAMENTO" com escopo incluindo "Setup Playwright" como primeiro item. No entanto, o
src/Web/package.json(context snippet) mostra que@nx/playwrighte@playwright/testjá estão instalados no workspace.Isso sugere que:
- O setup do Playwright já foi iniciado em sprint anterior, OU
- O escopo do Sprint 8E deve focar na implementação de testes (cenários, specs) ao invés de setup
Considere atualizar o escopo para refletir o trabalho real pendente.
📋 Escopo refinado sugerido para Sprint 8E
**Scope**: -1. **Setup Playwright**: Configurar Playwright no workspace NX -2. **Customer Web App Tests**: Login, busca, perfil, agendamento +1. **Playwright Configuration**: Configurar ambientes (dev/staging) e CI integration +2. **Customer Web App Tests**: Implementar specs - Login, busca, perfil, agendamento 3. **Provider Web App Tests**: Onboarding, dashboard, gestão de serviços 4. **Admin Portal Tests**: CRUD providers, documentos, métricas -5. **Pipeline Integration**: Adicionar steps em `pr-validation.yml` e `master-ci-cd.yml` +5. **CI/CD Integration**: Adicionar Playwright steps em pipelines existentes🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap-current.md` around lines 617 - 637, The Sprint 8E doc incorrectly lists "Setup Playwright" in the Scope even though Playwright is already present in src/Web/package.json; update the "### ⏳ Sprint 8E - E2E Tests React Apps (Playwright)" section to remove or de-emphasize "Setup Playwright" and instead replace it with explicit implementation tasks (e.g., "Implement Playwright test specs and test suites", "Add CI steps for Playwright in pr-validation.yml and master-ci-cd.yml") and adjust the Status/Branch notes as needed so the Scope reflects implementing tests (the heading text, the Scope list, and the first bullet "Setup Playwright" are the identifiers to edit).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@docs/admin-portal/overview.md`:
- Around line 125-202: The docs still contain Blazor/Razor examples
(AuthorizeView, `@attribute`, `@inject` LocalizationService, MudButton/MudText,
DialogService.ShowMessageBox); replace these with React/TSX examples using your
app conventions: show a ProtectedPage component using next-auth's useSession (or
your auth hook) to gate UI (e.g., ProtectedPage -> const { data: session } =
useSession(); session?.user?.role === 'admin' ? <Button>Editar</Button> :
<Text>Sem permissão</Text>), replace `@inject` LocalizationService L and
L.GetString(...) with your i18n hook (e.g., const { t } = useTranslation();
<Button>{t('Common.Save')}</Button>), and swap DialogService.ShowMessageBox
examples for your React dialog API or a window.confirm fallback (e.g.,
showModal/showConfirm or custom <ConfirmDialog />); update code blocks and
explanatory text accordingly so all examples use React/TSX symbols
(ProtectedPage, useSession, useTranslation, Button, Text, showModal).
- Around line 35-102: The docs still describe a Blazor WASM architecture and
.razor/Fluxor artifacts; update the Mermaid diagram (replace "Admin Portal
(Blazor WASM)" and nodes State, Effects, API labeled as Fluxor/Refit with
Next.js/React, Zustand (or equivalent) and TanStack Query and adjust arrows
accordingly using the existing node names (UI, State, Effects, API, Gateway,
Modules) or renaming UI->ReactComponents and State->Zustand/Store so the flow
maps to API Gateway and Backend modules; also replace the directory tree under
src/Web/MeAjudaAi.Web.Admin/ to reflect the React/Next.js layout by removing
.razor files and the Features/Fluxor folder and adding app/, (admin)/,
components/, hooks/, lib/ (keep references to package.json/Next.js where
applicable) so the file list and diagram match the Sprint 8D migration.
In `@docs/architecture.md`:
- Around line 2829-3110: This section contains ~280 lines of obsolete
Blazor/Fluxor/Refit/MudBlazor examples (notably ProvidersState,
ProvidersActions, ProvidersReducers, ProvidersEffects, IProvidersApi,
IDocumentsApi, IServiceCatalogsApi, MudDataGrid, MudPagination, MudCard, etc.)
that conflict with the React/Next.js migration; remove these legacy blocks from
docs/architecture.md and either (a) move them into a new historical file (e.g.,
docs/admin-portal/legacy/blazor-architecture.md) preserving the original
content, or (b) replace them with concise React equivalents (e.g., mention
Zustand store patterns and TanStack Query hooks plus example filenames like
stores/providersStore.ts and hooks/useProviders.ts) so the architecture doc
reflects the current Admin Portal tech stack.
In `@docs/roadmap.md`:
- Line 36: Atualize a linha que atualmente diz "Admin Portal atualmente em
Blazor WASM; migração para React planejada para o Sprint 8D." para refletir que
o Sprint 8D foi concluído em 24 de março de 2026; altere o texto para algo como
"Admin Portal migrado de Blazor WASM para React durante o Sprint 8D (concluído
em 24 de março de 2026)." e garanta que qualquer menção a "planejada" ou
"planejada para o Sprint 8D" seja removida ou convertida para status concluído.
In `@README.md`:
- Around line 107-108: The README's project tree still labels
MeAjudaAi.Web.Admin as "Admin Portal (Blazor WASM)"; update that entry to
reflect the completed migration to React (e.g., "Admin Portal (React)") so it
matches the Sprint 8D changes and PR description; locate the line referencing
the MeAjudaAi.Web.Admin folder in README.md and replace the platform note
accordingly.
---
Nitpick comments:
In `@docs/roadmap-current.md`:
- Around line 617-637: The Sprint 8E doc incorrectly lists "Setup Playwright" in
the Scope even though Playwright is already present in src/Web/package.json;
update the "### ⏳ Sprint 8E - E2E Tests React Apps (Playwright)" section to
remove or de-emphasize "Setup Playwright" and instead replace it with explicit
implementation tasks (e.g., "Implement Playwright test specs and test suites",
"Add CI steps for Playwright in pr-validation.yml and master-ci-cd.yml") and
adjust the Status/Branch notes as needed so the Scope reflects implementing
tests (the heading text, the Scope list, and the first bullet "Setup Playwright"
are the identifiers to edit).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5fa87749-bf79-4c32-94ed-ebc716a03621
📒 Files selected for processing (7)
README.mddocs/admin-portal/features.mddocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mddocs/roadmap.mddocs/technical-debt.md
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (7)
src/Web/playwright.config.ts (1)
18-39: Configuração de projetos incompatível com CI.A configuração define 5 projetos de browser, mas os workflows CI (
pr-validation.ymlemaster-ci-cd.yml) instalam apenas o Chromium. Quando os steps de E2E forem habilitados, os testes falharão para Firefox, WebKit e browsers mobile.Opções para resolver:
- Instalar todos os browsers no CI (mais cobertura, mas mais lento e usa mais espaço)
- Filtrar para chromium no CI (recomendado para começar)
- Criar perfil CI-only no config
♻️ Opção 2: Adicionar projeto CI-only
projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, + // Browsers adicionais - executar apenas localmente ou em pipeline completa { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, { name: 'Mobile Chrome', use: { ...devices['Pixel 5'] }, }, { name: 'Mobile Safari', use: { ...devices['iPhone 12'] }, }, ],E nos workflows, usar
--project=chromiumaté que o pipeline esteja estabilizado.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/playwright.config.ts` around lines 18 - 39, The Playwright config's projects array declares five projects ('chromium', 'firefox', 'webkit', 'Mobile Chrome', 'Mobile Safari') but the CI only installs Chromium, causing CI E2E failures; fix by either installing all browsers in CI or limiting CI runs to Chromium — the minimal change is to add a CI-only profile or update the CI test invocation to pass --project=chromium (or create a new profile in the Playwright config that only includes the 'chromium' project and have CI use that profile) so CI only runs the supported browser.src/Web/e2e/admin/auth.spec.ts (2)
12-15: Usar assertions com auto-wait do Playwright.A assertion
expect(page.url()).toContain(...)não possui auto-wait e pode causar flakiness. O Playwright recomenda usarexpect(page).toHaveURL()que aguarda automaticamente a navegação.♻️ Sugestão de correção
test('should navigate to login', async ({ page }) => { - await page.click('text=Login Admin'); - await expect(page.url()).toContain('/admin/login'); + await page.getByText('Login Admin').click(); + await expect(page).toHaveURL(/\/admin\/login/); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/e2e/admin/auth.spec.ts` around lines 12 - 15, Replace the non-waiting assertion that checks the URL after clicking "Login Admin": after calling page.click('text=Login Admin') use Playwright's auto-waiting assertion await expect(page).toHaveURL(...) instead of expect(page.url()).toContain(...); update the test named 'should navigate to login' to await the navigation with expect(page).toHaveURL (use the '/admin/login' path or a suitable pattern) so the test reliably waits for the route change.
23-29: Considerar case-insensitivity para mensagens de erro.A assertion
text=credenciais inválidasé case-sensitive e específica para português. Se o texto da mensagem mudar ligeiramente, o teste falhará.♻️ Sugestão de melhoria
test('should show error for invalid credentials', async ({ page }) => { await page.goto('/admin/login'); await page.fill('input[type="email"]', 'admin@meajudaai.com'); await page.fill('input[type="password"]', 'wrongpassword'); await page.click('button[type="submit"]'); - await expect(page.locator('text=credenciais inválidas')).toBeVisible(); + await expect(page.getByText(/credenciais inválidas/i)).toBeVisible(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/e2e/admin/auth.spec.ts` around lines 23 - 29, The test "should show error for invalid credentials" uses a case-sensitive locator 'text=credenciais inválidas' which will break on capitalization or minor text changes; update the assertion to perform a case-insensitive match (for example use a case-insensitive regex or normalize the locator text) when checking the error message so the expect on the locator (currently referencing 'text=credenciais inválidas') becomes robust to casing and small variations..github/workflows/pr-validation.yml (1)
182-194: Adicionar filtro de projeto para corresponder aos browsers instalados.O step instala apenas o Chromium (
npx playwright install --with-deps chromium), masplaywright.config.tsdefine 5 projetos (chromium, firefox, webkit, Mobile Chrome, Mobile Safari). Quando este step for habilitado, os testes irão falhar para os browsers não instalados.♻️ Sugestão de correção
- name: Run E2E Tests (Playwright) working-directory: ./src/Web if: false # Disabled for now - enable after apps are running run: | echo "================================" echo "E2E TESTS (PLAYWRIGHT)" echo "================================" # Install Playwright browsers npx playwright install --with-deps chromium # Run E2E tests - npx playwright test --reporter=list + npx playwright test --project=chromium --reporter=list🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/pr-validation.yml around lines 182 - 194, O step "Run E2E Tests (Playwright)" instala apenas Chromium via "npx playwright install --with-deps chromium" enquanto "playwright.config.ts" define cinco projects; isso fará os testes falharem para browsers não instalados. Corrija instalando todos os browsers usados (remover "chromium" para rodar "npx playwright install --with-deps" sem filtro) ou altere a execução "npx playwright test --reporter=list" para usar o filtro de projeto correspondente (ex.: "--project=chromium" ou listar explicitamente os projetos instalados) de modo que os projects em playwright.config.ts correspondam aos browsers instalados..github/workflows/master-ci-cd.yml (1)
167-179: Corrigir trailing spaces e adicionar filtro de projeto.O yamllint detectou espaços em branco no final das linhas 174 e 177. Além disso, assim como em
pr-validation.yml, o comando instala apenas chromium mas executa todos os projetos.♻️ Sugestão de correção
- name: Run E2E Tests (Playwright) - working-directory: src/Web + working-directory: ./src/Web if: false # Disabled for now - enable after apps are running run: | echo "================================" echo "E2E TESTS (PLAYWRIGHT)" echo "================================" - + # Install Playwright browsers npx playwright install --with-deps chromium - + # Run E2E tests - npx playwright test --reporter=list + npx playwright test --project=chromium --reporter=list🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/master-ci-cd.yml around lines 167 - 179, O job "Run E2E Tests (Playwright)" tem espaços em branco finais e instala apenas chromium mas executa todos os projetos; remova os trailing spaces nas linhas correspondentes (as linhas onde aparecem espaços ao final) e alinhe os comandos: mantenha "npx playwright install --with-deps chromium" como instalador e altere o test runner "npx playwright test --reporter=list" para filtrar o projeto instalado (por exemplo adicionando "--project=chromium") para que apenas o projeto chromium seja executado.src/Web/e2e/customer/auth.spec.ts (2)
8-10: A asserção da landing page está genérica demais.Na Line 9, validar só
h1visível pode gerar falso positivo. Prefira conferir heading esperado (texto/role) ou umdata-testidda landing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/e2e/customer/auth.spec.ts` around lines 8 - 10, A asserção no teste 'should display landing page' está demasiado genérica (usa page.locator('h1')); substitua-a por uma verificação mais específica: localizar o heading esperado por texto/role ou por um seletor data-testid (ex.: page.getByRole('heading', { name: 'Texto Esperado' }) ou page.locator('[data-testid="landing-heading"]')) e usar toBeVisible()/toHaveText() conforme apropriado para validar conteúdo e evitar falsos positivos.
23-29: Deixe a validação de erro menos frágil a variações de UI/i18n.Na Line 28, o seletor por texto literal pode quebrar com pequenas mudanças (“Credenciais inválidas.”). Prefira
getByRole('alert')+ regex case-insensitive.Diff sugerido
test('should show error for invalid credentials', async ({ page }) => { await page.goto('/login'); await page.fill('input[type="email"]', 'invalid@test.com'); await page.fill('input[type="password"]', 'wrongpassword'); await page.click('button[type="submit"]'); - await expect(page.locator('text=credenciais inválidas')).toBeVisible(); + await expect(page.getByRole('alert')).toContainText(/credenciais inválidas/i); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/e2e/customer/auth.spec.ts` around lines 23 - 29, The test "should show error for invalid credentials" uses a fragile text selector; change the assertion to target the ARIA alert role instead (use page.getByRole('alert') with a case-insensitive regex) so it no longer depends on exact UI/i18n text; update the assertion referencing the existing test block and replace the expect(page.locator('text=credenciais inválidas')).toBeVisible() with an expectation against page.getByRole('alert').toContainText(/credenciais inválidas/i) (or similar regex) to make the check robust.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Web/e2e/admin/providers.spec.ts`:
- Around line 12-16: The test "should search providers" uses a weak success
criterion (.toBeVisible()) which can produce false positives; update the test
that fills searchInput (variable searchInput) to assert that the provider rows
(locator '[data-testid="provider-row"]') actually reflect the query by checking
their text content includes the search term (e.g., contains 'João') and/or that
non-matching rows are not visible, and optionally assert the count of matched
rows changes compared to an unfiltered state; apply the same stronger assertions
to the analogous filter test(s) that currently only call .toBeVisible().
- Around line 31-40: The two tests named "should approve document" and "should
reject document" are racing for the same pending document because they use
generic selectors (page.goto('/admin/documentos') and
button:has-text("Aprovar"/"Rejeitar")) and run fullyParallel; add isolation by
creating a unique fixture per test in test.beforeEach (call your backend API or
test helper to create/reset a single pending document and return its id), then
target that specific document in each test (use a deterministic selector
containing the returned id or navigate to the document-specific URL) and ensure
teardown/reset after each test so the approve and reject flows operate on
independent documents.
In `@src/Web/e2e/base.ts`:
- Around line 5-9: O fixture estendido test = base.extend({ page: async ({ page
}, use) => { await page.goto('/'); await use(page); }, }) está navegando
automaticamente para '/' antes de cada teste, causando navegação duplicada com
os test.beforeEach dos specs (por exemplo provider/onboarding.spec.ts); remova a
chamada await page.goto('/') do fixture (ou alternativamente delete os
beforeEach redundantes nos specs que também navegam para '/'), deixando que cada
spec controle sua própria navegação; edite a função page no extend para apenas
usar(page) sem navegar.
In `@src/Web/e2e/customer/auth.spec.ts`:
- Around line 12-15: No teste "should navigate to login page" substitua a
asserção que usa expect(page.url()).toContain('/login') por uma asserção
auto-retrying: após page.click('text=Entrar') use await
expect(page).toHaveURL(...) (por exemplo await
expect(page).toHaveURL(/.*\/login/) ou await expect(page).toHaveURL('**/login')
) para aguardar a navegação e evitar flakiness.
In `@src/Web/e2e/customer/search.spec.ts`:
- Around line 19-24: In the 'should filter by location' test, remove the leading
space from the input value passed to locationInput.fill — replace ' Rio de
Janeiro' with 'Rio de Janeiro' in the test body (the test function named "should
filter by location" using the locator stored in locationInput) so the test sends
the correct string without the stray leading whitespace.
In `@src/Web/e2e/provider/auth.spec.ts`:
- Around line 12-15: O teste "should navigate to login page" usa
page.click('text=Login Prestador') e atualmente verifica
expect(page.url()).toContain('/login') — atualize essa asserção para verificar o
path correto (por exemplo '/provider/login') para evitar falsos positivos;
localize a declaração do teste (test('should navigate to login page', async ({
page }) => { ... })) e substituir a expectativa por uma verificação mais
específica como expect(page.url()).toContain('/provider/login') ou a string de
rota correta da aplicação.
In `@src/Web/e2e/provider/onboarding.spec.ts`:
- Around line 12-18: O teste "should complete basic info step" está usando um
CPF inválido (12345678900) que pode acionar validação e quebrar o teste; update
o CPF value usado in the test to a known-valid test CPF (e.g. 52998224725) in
the page.fill call for 'input[name="cpf"]' so the form validation passes and the
assertion that the URL contains '/onboarding/documentos' can be reached.
In `@src/Web/playwright.config.ts`:
- Around line 40-45: No script `next:dev` exists; update the Playwright
webServer configuration's command (webServer.command) to use the correct Next.js
start script by replacing 'npm run next:dev' with 'npm run dev' so Playwright
launches the app with the defined package.json script.
---
Nitpick comments:
In @.github/workflows/master-ci-cd.yml:
- Around line 167-179: O job "Run E2E Tests (Playwright)" tem espaços em branco
finais e instala apenas chromium mas executa todos os projetos; remova os
trailing spaces nas linhas correspondentes (as linhas onde aparecem espaços ao
final) e alinhe os comandos: mantenha "npx playwright install --with-deps
chromium" como instalador e altere o test runner "npx playwright test
--reporter=list" para filtrar o projeto instalado (por exemplo adicionando
"--project=chromium") para que apenas o projeto chromium seja executado.
In @.github/workflows/pr-validation.yml:
- Around line 182-194: O step "Run E2E Tests (Playwright)" instala apenas
Chromium via "npx playwright install --with-deps chromium" enquanto
"playwright.config.ts" define cinco projects; isso fará os testes falharem para
browsers não instalados. Corrija instalando todos os browsers usados (remover
"chromium" para rodar "npx playwright install --with-deps" sem filtro) ou altere
a execução "npx playwright test --reporter=list" para usar o filtro de projeto
correspondente (ex.: "--project=chromium" ou listar explicitamente os projetos
instalados) de modo que os projects em playwright.config.ts correspondam aos
browsers instalados.
In `@src/Web/e2e/admin/auth.spec.ts`:
- Around line 12-15: Replace the non-waiting assertion that checks the URL after
clicking "Login Admin": after calling page.click('text=Login Admin') use
Playwright's auto-waiting assertion await expect(page).toHaveURL(...) instead of
expect(page.url()).toContain(...); update the test named 'should navigate to
login' to await the navigation with expect(page).toHaveURL (use the
'/admin/login' path or a suitable pattern) so the test reliably waits for the
route change.
- Around line 23-29: The test "should show error for invalid credentials" uses a
case-sensitive locator 'text=credenciais inválidas' which will break on
capitalization or minor text changes; update the assertion to perform a
case-insensitive match (for example use a case-insensitive regex or normalize
the locator text) when checking the error message so the expect on the locator
(currently referencing 'text=credenciais inválidas') becomes robust to casing
and small variations.
In `@src/Web/e2e/customer/auth.spec.ts`:
- Around line 8-10: A asserção no teste 'should display landing page' está
demasiado genérica (usa page.locator('h1')); substitua-a por uma verificação
mais específica: localizar o heading esperado por texto/role ou por um seletor
data-testid (ex.: page.getByRole('heading', { name: 'Texto Esperado' }) ou
page.locator('[data-testid="landing-heading"]')) e usar
toBeVisible()/toHaveText() conforme apropriado para validar conteúdo e evitar
falsos positivos.
- Around line 23-29: The test "should show error for invalid credentials" uses a
fragile text selector; change the assertion to target the ARIA alert role
instead (use page.getByRole('alert') with a case-insensitive regex) so it no
longer depends on exact UI/i18n text; update the assertion referencing the
existing test block and replace the expect(page.locator('text=credenciais
inválidas')).toBeVisible() with an expectation against
page.getByRole('alert').toContainText(/credenciais inválidas/i) (or similar
regex) to make the check robust.
In `@src/Web/playwright.config.ts`:
- Around line 18-39: The Playwright config's projects array declares five
projects ('chromium', 'firefox', 'webkit', 'Mobile Chrome', 'Mobile Safari') but
the CI only installs Chromium, causing CI E2E failures; fix by either installing
all browsers in CI or limiting CI runs to Chromium — the minimal change is to
add a CI-only profile or update the CI test invocation to pass
--project=chromium (or create a new profile in the Playwright config that only
includes the 'chromium' project and have CI use that profile) so CI only runs
the supported browser.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 506c5cdf-9aec-4f83-92d3-e88aadc01b84
📒 Files selected for processing (10)
.github/workflows/master-ci-cd.yml.github/workflows/pr-validation.ymlsrc/Web/e2e/admin/auth.spec.tssrc/Web/e2e/admin/providers.spec.tssrc/Web/e2e/base.tssrc/Web/e2e/customer/auth.spec.tssrc/Web/e2e/customer/search.spec.tssrc/Web/e2e/provider/auth.spec.tssrc/Web/e2e/provider/onboarding.spec.tssrc/Web/playwright.config.ts
Admin Portal Documentation: - Replace Blazor/Razor examples with React/TSX (useSession, useTranslation, etc.) - Update Mermaid diagram to show React + Next.js architecture - Update directory structure to reflect React/Next.js layout - Replace Fluxor/Refit patterns with Zustand/TanStack Query Roadmap: - Update Sprint 8D status (completed Mar 24, 2026) - Update Sprint 8E scope (remove 'Setup Playwright' - already present) README: - Update project tree to reflect React apps (Admin, Customer, Provider) Architecture: - Replace Fluxor pattern with Zustand examples - Replace Refit with TanStack Query examples - Update best practices for React/Next.js E2E Tests: - Fix base.ts: remove auto navigation to '/' - Fix customer/auth.spec.ts: use expect(page).toHaveURL, getByRole - Fix customer/search.spec.ts: remove leading whitespace - Fix provider/auth.spec.ts: correct path '/provider/login' - Fix provider/onboarding.spec.ts: use valid CPF - Fix admin/auth.spec.ts: use expect(page).toHaveURL, case-insensitive - Fix admin/providers.spec.ts: stronger assertions, document isolation Playwright Config: - Fix webServer command: 'npm run dev' instead of 'npm run next:dev' - Add 'ci' project for chromium-only CI runs Pipelines: - Update to use --project=ci filter
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/architecture.md (1)
2916-2931:⚠️ Potential issue | 🟠 MajorRemover trecho órfão legado após o exemplo de TanStack Query.
Após o fechamento do bloco TypeScript, ficou conteúdo de Fluxor/C# fora de contexto. Isso quebra a narrativa da arquitetura React e confunde a referência técnica.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 2916 - 2931, Remover trecho órfão de Fluxor/C# que foi deixado após o bloco TypeScript; localize e apagar o bloco que contém dispatcher.Dispatch e LoadProvidersFailureAction (o catch/else com result.Error?.Message e dispatcher.Dispatch(new LoadProvidersFailureAction(...))) que aparece imediatamente depois do exemplo de TanStack Query/TypeScript para que o documento contenha apenas o exemplo TypeScript relevante e não código C# fora de contexto.
🧹 Nitpick comments (2)
.github/workflows/master-ci-cd.yml (1)
167-179: Inconsistência noworking-directoryentre workflows.O
pr-validation.ymlusa./src/Web(linha 183) enquanto este arquivo usasrc/Web(linha 168). Ambos funcionam, mas padronizar melhora a manutenibilidade.♻️ Padronizar path com prefixo `./`
- name: Run E2E Tests (Playwright) - working-directory: src/Web + working-directory: ./src/Web if: false # Disabled for now - enable after apps are running🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/master-ci-cd.yml around lines 167 - 179, Padronize o path do campo working-directory no job "Run E2E Tests (Playwright)" para usar o prefixo ./ como no outro workflow; atualize o valor atual "src/Web" para "./src/Web" (localize pelo nome do job "Run E2E Tests (Playwright)" e pela chave working-directory) para manter consistência entre os workflows..github/workflows/pr-validation.yml (1)
182-194: Step de E2E Playwright corretamente configurado.A implementação está alinhada com o
playwright.config.ts(projetociexiste,webServerinicia automaticamente). O aviso doactionlintsobreif: falseé esperado para placeholders intencionais.Sugestão para facilitar a ativação futura: considerar usar um input de workflow ou variável de ambiente ao invés de
if: falsehardcoded, para permitir testes manuais viaworkflow_dispatch.♻️ Sugestão para controle dinâmico
+ # At workflow level, add input: + # workflow_dispatch: + # inputs: + # run_e2e_playwright: + # description: 'Run Playwright E2E tests' + # required: false + # default: false + # type: boolean - name: Run E2E Tests (Playwright) working-directory: ./src/Web - if: false # Disabled for now - enable after apps are running + if: ${{ github.event.inputs.run_e2e_playwright == 'true' }} # Enable via workflow_dispatch or set to true when ready run: |🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/pr-validation.yml around lines 182 - 194, Replace the hardcoded "if: false" on the "Run E2E Tests (Playwright)" step with a dynamic conditional driven by a workflow input or environment variable so the step can be enabled manually (e.g., via workflow_dispatch) without editing the file; locate the step named "Run E2E Tests (Playwright)" in the workflow and change its conditional to reference an input (like inputs.run_e2e == 'true') or an env var (like env.RUN_E2E == 'true'), and update the workflow inputs/defaults or env setup accordingly to provide a clear on/off toggle for future activation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/admin-portal/overview.md`:
- Around line 99-101: Atualize o trecho em docs/admin-portal/overview.md que
lista "e2e/" e "playwright.config.ts" para refletir a localização real dos
artefatos; substitua as entradas por "src/Web/e2e/" e
"src/Web/playwright.config.ts" (ou equivalente usado no workspace) garantindo
que o exemplo de árvore mostre essas pastas/arquivos corretamente e mantenha a
formatação consistente com o restante do documento.
- Around line 145-146: Replace the non-existent <Redirect /> usage in the
AdminProtected client component with next/navigation's router.push: import
useRouter from 'next/navigation', call const router = useRouter(), and return
router.push('/login') instead of rendering <Redirect />; also ensure you handle
the loading state (status === 'loading') with Spinner and keep the existing role
check (session.user.role !== 'admin') returning <AccessDenied /> so the flow is:
useSession -> handle loading -> if no session call router.push('/login') -> if
not admin return <AccessDenied />.
In `@docs/architecture.md`:
- Around line 3254-3273: The docs mix React/Next and Blazor artifacts in the
same tree; remove Blazor-specific entries (Program.cs, App.razor,
MeAjudaAi.Web.Admin.Tests) from the apps/admin-portal React tree and either move
them into a separate Blazor app section or create a distinct
apps/admin-portal-blazor subtree; update the diagram so that the React structure
only contains Next.js files (src/app, components, hooks, lib, stores, e2e,
playwright.config.ts, package.json) and ensure any references to
Program.cs/App.razor/MeAjudaAi.Web.Admin.Tests are relocated to the
Blazor-specific documentation area.
- Line 3038: Update the documentation line that currently claims "✅ Reutilizável
entre projetos (.NET, Node.js)" by removing the Node.js reference and clarifying
Refit's platform support; replace that phrase with something like "✅
Reutilizável entre projetos .NET (ex.: .NET 6/8, Xamarin, Blazor, UWP) / .NET
Standard 2.0" or equivalent wording to state Refit is .NET/C# only and does not
officially support Node.js, referencing the library name "Refit" for locating
the text to change.
In `@docs/roadmap-current.md`:
- Around line 1214-1216: The summary line for "Sprint 8E: E2E Tests React Apps
(Playwright)" is set to "Planejada" but the sprint block indicates it is "EM
ANDAMENTO"; update the summary entry for that exact string to match the sprint
block by changing its status and icon to the same "EM ANDANDO"/in‑progress label
used in the sprint block (i.e., replace "Planejada" and its icon with the
in‑progress wording/icon used elsewhere) so both occurrences of "Sprint 8E: E2E
Tests React Apps (Playwright)" are identical.
- Around line 604-606: O título "### ✅ Sprint 8D - Admin Portal Migration (2 -
22 Abr 2026)" e a linha "**Status**: ✅ CONCLUÍDA (24 Mar 2026)" estão em
conflito; atualize um para que ambas as datas coincidam — por exemplo, setar a
data de conclusão para "22 Abr 2026" na linha de status ou alterar o intervalo
no título para "(2 - 24 Mar 2026)"; modifique as strings exatas "### ✅ Sprint 8D
- Admin Portal Migration (2 - 22 Abr 2026)" e "**Status**: ✅ CONCLUÍDA (24 Mar
2026)" para a opção corrigida e verifique consistência em quaisquer referências
posteriores a Sprint 8D no documento.
In `@docs/roadmap.md`:
- Around line 10-11: The roadmap lists "Sprint 8E" both as the current sprint
and again under "Próximas Sprints"; update the bullet list so the upcoming
sprints start with the next sequential sprint (e.g., change the first entry
under "Próximas Sprints" from "8E (E2E Tests)" to "9 (Buffer & Risk Mitigation)"
or otherwise remove the duplicate "8E"), ensuring the "Sprint Atual" line
remains "8E (E2E Tests)" and the "Próximas Sprints" list no longer contains
"Sprint 8E".
In `@README.md`:
- Around line 272-273: A seção do Admin Portal está com texto híbrido (menciona
Blazor apesar de os bullets serem "Admin Portal React com Tailwind CSS" e "E2E
Tests com Playwright"); abra a seção que contém o título/descrição atual do
Admin Portal e substitua a descrição introdutória que refere Blazor por uma que
mencione React e Tailwind (ou remova qualquer referência a Blazor), garantindo
que o cabeçalho "Admin Portal React com Tailwind CSS" e a frase introdutória
estejam coerentes com os bullets e com os testes E2E com Playwright.
---
Outside diff comments:
In `@docs/architecture.md`:
- Around line 2916-2931: Remover trecho órfão de Fluxor/C# que foi deixado após
o bloco TypeScript; localize e apagar o bloco que contém dispatcher.Dispatch e
LoadProvidersFailureAction (o catch/else com result.Error?.Message e
dispatcher.Dispatch(new LoadProvidersFailureAction(...))) que aparece
imediatamente depois do exemplo de TanStack Query/TypeScript para que o
documento contenha apenas o exemplo TypeScript relevante e não código C# fora de
contexto.
---
Nitpick comments:
In @.github/workflows/master-ci-cd.yml:
- Around line 167-179: Padronize o path do campo working-directory no job "Run
E2E Tests (Playwright)" para usar o prefixo ./ como no outro workflow; atualize
o valor atual "src/Web" para "./src/Web" (localize pelo nome do job "Run E2E
Tests (Playwright)" e pela chave working-directory) para manter consistência
entre os workflows.
In @.github/workflows/pr-validation.yml:
- Around line 182-194: Replace the hardcoded "if: false" on the "Run E2E Tests
(Playwright)" step with a dynamic conditional driven by a workflow input or
environment variable so the step can be enabled manually (e.g., via
workflow_dispatch) without editing the file; locate the step named "Run E2E
Tests (Playwright)" in the workflow and change its conditional to reference an
input (like inputs.run_e2e == 'true') or an env var (like env.RUN_E2E ==
'true'), and update the workflow inputs/defaults or env setup accordingly to
provide a clear on/off toggle for future activation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 39c719ad-9505-4e51-86a3-a17538e27d7a
📒 Files selected for processing (15)
.github/workflows/master-ci-cd.yml.github/workflows/pr-validation.ymlREADME.mddocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mddocs/roadmap.mdsrc/Web/e2e/admin/auth.spec.tssrc/Web/e2e/admin/providers.spec.tssrc/Web/e2e/base.tssrc/Web/e2e/customer/auth.spec.tssrc/Web/e2e/customer/search.spec.tssrc/Web/e2e/provider/auth.spec.tssrc/Web/e2e/provider/onboarding.spec.tssrc/Web/playwright.config.ts
✅ Files skipped from review due to trivial changes (4)
- src/Web/e2e/admin/auth.spec.ts
- src/Web/e2e/provider/auth.spec.ts
- src/Web/e2e/customer/auth.spec.ts
- src/Web/playwright.config.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- src/Web/e2e/customer/search.spec.ts
- src/Web/e2e/base.ts
- src/Web/e2e/provider/onboarding.spec.ts
- src/Web/e2e/admin/providers.spec.ts
Admin Portal: - Fix e2e/playwright.config.ts paths to src/Web/ - Replace <Redirect /> with router.push in AdminProtected Architecture: - Fix Refit .NET-only statement - Remove orphaned Fluxor/C# code - Remove Blazor artifacts from React tree Roadmap: - Fix Sprint 8E status (Planejada -> Em Andamento) - Fix Sprint 8D dates (2-22 Abr -> 2-24 Mar) - Remove duplicate 8E from Próximas Sprints README: - Fix Admin Portal section (Blazor -> React) Pipelines: - Add ./ prefix to master-ci-cd.yml working-directory - Add dynamic run_e2e input to pr-validation.yml
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/master-ci-cd.yml:
- Around line 167-179: Add the missing frontend build steps before the "Run E2E
Tests (Playwright)" step and enable that step: in
.github/workflows/master-ci-cd.yml, insert the same build sequence used in
pr-validation.yml for the ./src/Web workspace (run npm install in ./src/Web and
then npm run build for the Next.js apps) so the Playwright tests have a built
app to run against, and then remove the if: false guard from the "Run E2E Tests
(Playwright)" step (working-directory: ./src/Web) to enable E2E execution.
In `@docs/admin-portal/overview.md`:
- Around line 217-226: E2E tests in src/Web/e2e/admin/auth.spec.ts assume
email/password inputs that no longer exist because login uses Keycloak OAuth
(see src/Web/MeAjudaAi.Web.Admin/app/login/page.tsx with the "Entrar com
Keycloak" button); update the tests to exercise the OAuth flow instead: replace
queries for input[type="email"] and input[type="password"] with assertions that
clicking the Keycloak button triggers a navigation to the Keycloak auth URL, add
a route/network intercept or mock for the OAuth callback to simulate a
successful token exchange, and then assert the app redirects to /dashboard;
ensure tests verify the redirect and session state rather than non-existent form
fields.
In `@docs/architecture.md`:
- Around line 3224-3240: The docs' file tree incorrectly implies a multi-project
Playwright setup; update the wording in docs/architecture.md to reflect the
actual src/Web/playwright.config.ts implementation by stating that the
Playwright config defines browser/device projects via the projects array (e.g.,
entries like 'chromium', 'firefox', 'webkit', mobile devices) and that all tests
use a single testDir ('./e2e') and a single baseURL ('http://localhost:3000'),
rather than separate app-specific projects (admin/customer/provider); reference
the projects array, testDir and baseURL symbols when editing the text or
removing/annotating the src/Web/playwright.config.ts line in the tree so readers
aren’t misled about per-app Playwright projects.
In `@docs/roadmap-current.md`:
- Around line 624-630: The roadmap incorrectly marks CI integration as complete;
update the Sprint 8E scope line (the bullet referencing "CI Integration" /
"Adicionar steps em `pr-validation.yml` e `master-ci-cd.yml`") to reflect that
CI is pending (suggested text: "Setup Playwright completo, integração CI
pendente") OR enable the pipelines by modifying `pr-validation.yml` to remove
the conditional `if: env.RUN_E2E == 'true'` defaulting to false (or set the
default to 'true') and re-enable master pipeline E2E steps by changing `if:
false` in `master-ci-cd.yml`; reference `env.RUN_E2E`, `pr-validation.yml`, and
`master-ci-cd.yml` when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bf85afcd-33e7-4db6-aa17-142b4ab8512c
📒 Files selected for processing (7)
.github/workflows/master-ci-cd.yml.github/workflows/pr-validation.ymlREADME.mddocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mddocs/roadmap.md
✅ Files skipped from review due to trivial changes (1)
- README.md
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/pr-validation.yml
- Move E2E tests from src/Web/e2e/ to tests/MeAjudaAi.Web.*.Tests/e2e/ - Create MeAjudaAi.Web.Shared.Tests with shared fixtures - Update playwright.config.ts to point to tests/ - Update imports in all test files - Update documentation to reflect new structure
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/architecture.md (1)
3012-3075:⚠️ Potential issue | 🟠 MajorExemplos de código ainda usam MudBlazor/Razor após migração para React.
Esta seção ainda contém exemplos de código Blazor/MudBlazor (ex:
<MudDataGrid>,<MudCard>,<MudText>, sintaxe Razor@code {}) que são inconsistentes com a migração documentada para React + Tailwind CSS.Os exemplos deveriam ser atualizados para mostrar componentes React equivalentes ou removidos para evitar confusão.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 3012 - 3075, The docs section mixes Blazor/MudBlazor examples with the React migration; replace or remove the MudBlazor/Razor snippets (e.g., <MudDataGrid>, <MudCard>, <MudText>, Razor syntax like `@context/`@State/@TotalPages) and provide React+Tailwind equivalents (or plain React component pseudo-code) that match the surrounding Layout/AppBar/Drawer examples, ensuring props and behavior (pagination, KPI cards, status chip) are represented using React component names and JSX syntax.docs/admin-portal/overview.md (1)
272-276:⚠️ Potential issue | 🟡 MinorLinks de documentação desatualizados após migração para React.
A seção "Links Úteis" ainda referencia documentação de Blazor/MudBlazor/Fluxor, que não é mais relevante após a migração para React + Next.js.
## 🔗 Links Úteis -- [MudBlazor Documentation](https://mudblazor.com/) -- [Fluxor Documentation](https://github.com/mrpmorris/Fluxor) -- [Blazor WebAssembly Guide](https://learn.microsoft.com/en-us/aspnet/core/blazor/) +- [React Documentation](https://react.dev/) +- [Next.js Documentation](https://nextjs.org/docs) +- [Tailwind CSS Documentation](https://tailwindcss.com/docs) +- [Zustand Documentation](https://zustand-demo.pmnd.rs/) +- [TanStack Query Documentation](https://tanstack.com/query/latest) +- [Playwright Documentation](https://playwright.dev/docs/intro)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 272 - 276, The "## 🔗 Links Úteis" section still references Blazor/MudBlazor/Fluxor docs; update that Links Úteis block to point to React and Next.js ecosystem docs instead (e.g., React docs, Next.js docs, and any UI/state libraries your project uses such as Tailwind, MUI, or Redux). Locate the "## 🔗 Links Úteis" heading in overview.md and replace the three Blazor-specific URLs with the current recommended resources (React, Next.js, and the project's chosen UI/state library) and ensure link text is in Portuguese to match the document style.
♻️ Duplicate comments (1)
src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts (1)
1-1:⚠️ Potential issue | 🟠 MajorAdicione
loginAsAdminnobeforeEach— páginas admin requerem autenticação.O middleware da aplicação admin (NextAuth com
withAuth) protege todas as rotas exceto/admin/login. Sem autenticação, os testes serão redirecionados para login e falharão. A funçãologinAsAdminestá importada mas não utilizada.♻️ Corrigir padrão de autenticação
test.describe('Admin Portal - Providers Management', () => { test.beforeEach(async ({ page }) => { + await loginAsAdmin(page); await page.goto('/admin/providers'); }); test('should display providers table', async ({ page }) => {Aplique o mesmo padrão para ambas as suites ("Admin Portal - Providers Management" e "Admin Portal - Documents").
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts` at line 1, Os testes importam loginAsAdmin mas não o usam; adicione uma chamada a loginAsAdmin() dentro de um beforeEach para cada suite de testes que exige autenticação (as duas describes "Admin Portal - Providers Management" e "Admin Portal - Documents") para evitar redirecionamento ao /admin/login. Localize os blocos describe correspondentes e inserir beforeEach(async () => await loginAsAdmin()) antes dos seus testes para garantir que as páginas admin estejam autenticadas.
🧹 Nitpick comments (7)
src/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.ts (1)
1-1: Remover imports não utilizados.
loginAsCustomerelogoutsão importados mas não utilizados nesta suite de testes. Remova-os para manter o código limpo ou considere utilizá-los em testes que requerem autenticação prévia.♻️ Correção sugerida
-import { test, expect, loginAsCustomer, logout } from '@meajudaai/web-e2e-support'; +import { test, expect } from '@meajudaai/web-e2e-support';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.ts` at line 1, The imports loginAsCustomer and logout are unused in the test suite; remove them from the import statement (the line that currently imports test, expect, loginAsCustomer, logout from '@meajudaai/web-e2e-support') so only needed symbols (test, expect) are imported, or alternatively use those functions in an authentication test if intended—update the import to eliminate the unused identifiers to fix the lint/cleanup warning..github/workflows/master-ci-cd.yml (1)
187-188: Linha longa no script shell.A linha 187 excede 120 caracteres. Considere quebrar para melhor legibilidade.
♻️ Sugestão de formatação
- DLL_PATH=$(find ../../src/Bootstrapper/MeAjudaAi.ApiService/bin/Release -name "MeAjudaAi.ApiService.dll" | head -n 1) + DLL_PATH=$(find ../../src/Bootstrapper/MeAjudaAi.ApiService/bin/Release \ + -name "MeAjudaAi.ApiService.dll" | head -n 1)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/master-ci-cd.yml around lines 187 - 188, The long shell command assigning DLL_PATH exceeds 120 chars; split it for readability by breaking the find invocation across lines or by predefining parts: e.g., set a DIR_VAR and PATTERN_VAR (or use a multiline command substitution with backslashes) and then assign DLL_PATH using those smaller pieces (referencing the DLL_PATH variable and the find | head -n 1 pipeline), then call swagger tofile --output ../api/api-spec.json "$DLL_PATH" v1 as before; ensure quoting is preserved and line continuations or separate variables keep the same semantics.src/Web/libs/e2e-support/base.ts (4)
1-1: Remover import não utilizado:BrowserContext.O tipo
BrowserContexté importado mas nunca utilizado no arquivo.-import { test as base, Page, BrowserContext } from '@playwright/test'; +import { test as base, Page } from '@playwright/test';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` at line 1, The import list at the top of the file includes an unused symbol BrowserContext; remove BrowserContext from the import statement (import { test as base, Page } from '@playwright/test') and verify there are no remaining references to BrowserContext in this module (e.g., in helper functions or type annotations) before committing.
9-13: Fixture customizada não adiciona valor.A fixture
pageapenas repassa o objetopagepadrão do Playwright sem nenhuma modificação ou configuração adicional. Isso é redundante.Se a intenção é preparar para futuras customizações (ex: injetar autenticação automática), considere documentar essa intenção ou remover até que seja necessário.
-export const test = base.extend<TestFixtures>({ - page: async ({ page }, use) => { - await use(page); - }, -}); +// Re-export base test directly until custom fixtures are needed +export const test = base;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 9 - 13, The custom fixture declared via test = base.extend<TestFixtures> defines a page fixture that just forwards Playwright's page (page: async ({ page }, use) => { await use(page); }) which is redundant; either remove this custom page fixture and export test = base directly, or implement the intended customization (e.g., automatic auth injection, additional setup/teardown) inside the page fixture and add a short inline comment explaining the purpose; locate and update the test constant and the page fixture implementation to apply one of these two changes.
41-44: Seletor de texto é frágil para o botão de logout.O seletor
'text=Sair'pode quebrar com:
- Mudanças de idioma (i18n)
- Texto adicional no botão
- Múltiplos elementos com "Sair"
Prefira usar
getByRolecom acessibilidade oudata-testid:export async function logout(page: Page): Promise<void> { - await page.click('text=Sair'); + await page.getByRole('button', { name: /sair/i }).click(); await page.waitForURL(/\/(login|admin\/login|provider\/login)/); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 41 - 44, No logout selector should rely on fragile text; in the logout function replace the page.click('text=Sair') use a robust selector such as page.getByRole('button', { name: /sair/i }) or a stable data-testid (e.g. page.getByTestId('logout-button')) so the click targets the logout button by role/aria or test id; update the logout(Page) implementation to use that selector (and ensure the app exposes the matching aria-label or data-testid) and keep the existing await page.waitForURL(...) as is.
17-23: Tratamento silencioso de erros pode mascarar falhas reais.O
.catch()nas funções de login apenas loga uma mensagem genérica, mas não diferencia entre:
- Timeout esperado em mock/test mode
- Falha real de navegação ou elemento não encontrado
Considere uma abordagem mais robusta:
export async function loginAsAdmin(page: Page): Promise<void> { await page.goto('/admin/login'); await page.getByRole('button', { name: /entrar com keycloak/i }).click(); - await page.waitForURL(/.*keycloak.*|.*realms.*\/meajudaai/i, { timeout: 5000 }).catch(() => { - console.log('OAuth redirect intercepted - running in mock/test mode'); - }); + // Em ambiente de teste mockado, o redirect OAuth pode não ocorrer + const isMockMode = process.env.MOCK_AUTH === 'true'; + if (!isMockMode) { + await page.waitForURL(/.*keycloak.*|.*realms.*\/meajudaai/i, { timeout: 5000 }); + } }O mesmo padrão se aplica a
loginAsProvidereloginAsCustomer.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 17 - 23, The current silent .catch() on page.waitForURL in loginAsAdmin (and the same pattern in loginAsProvider and loginAsCustomer) masks real failures; update each login helper to explicitly handle Playwright TimeoutError vs other exceptions: call page.waitForURL(...) inside a try/catch, and in the catch inspect error.name or error.message (e.g., "TimeoutError") to treat only expected timeouts as the mock/test-mode case (log a specific message) while rethrowing or failing-fast for any other errors (navigation failures, element-not-found, etc.), and consider splitting the click and wait steps so element-not-found errors can be caught and reported separately.docs/admin-portal/overview.md (1)
107-112: Adicionar especificador de linguagem ao bloco de código.O bloco de código na linha 107 não tem linguagem especificada, o que gera aviso do markdownlint (MD040).
-``` +```text tests/MeAjudaAi.Web.Admin.Tests/🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 107 - 112, The fenced code block that contains the tree snippet starting with "tests/MeAjudaAi.Web.Admin.Tests/" is missing a language specifier and triggers markdownlint MD040; update that block to include a language identifier (e.g., change the opening fence to ```text or ```bash) so the block is explicitly annotated and the MD040 warning is resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/admin-portal/overview.md`:
- Around line 242-244: The README command for running Playwright E2E tests
points at a non-existent path; update the example under the cd src/Web step to
reflect the repository's Playwright discovery rules (testDir: './src' and grep:
/e2e/) by replacing the incorrect invocation `npx playwright test e2e/admin/`
with either `npx playwright test --grep "admin"` to run only admin tests or `npx
playwright test` to run all E2E tests so the documented commands match the
Playwright config and actual test discovery.
---
Outside diff comments:
In `@docs/admin-portal/overview.md`:
- Around line 272-276: The "## 🔗 Links Úteis" section still references
Blazor/MudBlazor/Fluxor docs; update that Links Úteis block to point to React
and Next.js ecosystem docs instead (e.g., React docs, Next.js docs, and any
UI/state libraries your project uses such as Tailwind, MUI, or Redux). Locate
the "## 🔗 Links Úteis" heading in overview.md and replace the three
Blazor-specific URLs with the current recommended resources (React, Next.js, and
the project's chosen UI/state library) and ensure link text is in Portuguese to
match the document style.
In `@docs/architecture.md`:
- Around line 3012-3075: The docs section mixes Blazor/MudBlazor examples with
the React migration; replace or remove the MudBlazor/Razor snippets (e.g.,
<MudDataGrid>, <MudCard>, <MudText>, Razor syntax like
`@context/`@State/@TotalPages) and provide React+Tailwind equivalents (or plain
React component pseudo-code) that match the surrounding Layout/AppBar/Drawer
examples, ensuring props and behavior (pagination, KPI cards, status chip) are
represented using React component names and JSX syntax.
---
Duplicate comments:
In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts`:
- Line 1: Os testes importam loginAsAdmin mas não o usam; adicione uma chamada a
loginAsAdmin() dentro de um beforeEach para cada suite de testes que exige
autenticação (as duas describes "Admin Portal - Providers Management" e "Admin
Portal - Documents") para evitar redirecionamento ao /admin/login. Localize os
blocos describe correspondentes e inserir beforeEach(async () => await
loginAsAdmin()) antes dos seus testes para garantir que as páginas admin estejam
autenticadas.
---
Nitpick comments:
In @.github/workflows/master-ci-cd.yml:
- Around line 187-188: The long shell command assigning DLL_PATH exceeds 120
chars; split it for readability by breaking the find invocation across lines or
by predefining parts: e.g., set a DIR_VAR and PATTERN_VAR (or use a multiline
command substitution with backslashes) and then assign DLL_PATH using those
smaller pieces (referencing the DLL_PATH variable and the find | head -n 1
pipeline), then call swagger tofile --output ../api/api-spec.json "$DLL_PATH" v1
as before; ensure quoting is preserved and line continuations or separate
variables keep the same semantics.
In `@docs/admin-portal/overview.md`:
- Around line 107-112: The fenced code block that contains the tree snippet
starting with "tests/MeAjudaAi.Web.Admin.Tests/" is missing a language specifier
and triggers markdownlint MD040; update that block to include a language
identifier (e.g., change the opening fence to ```text or ```bash) so the block
is explicitly annotated and the MD040 warning is resolved.
In `@src/Web/libs/e2e-support/base.ts`:
- Line 1: The import list at the top of the file includes an unused symbol
BrowserContext; remove BrowserContext from the import statement (import { test
as base, Page } from '@playwright/test') and verify there are no remaining
references to BrowserContext in this module (e.g., in helper functions or type
annotations) before committing.
- Around line 9-13: The custom fixture declared via test =
base.extend<TestFixtures> defines a page fixture that just forwards Playwright's
page (page: async ({ page }, use) => { await use(page); }) which is redundant;
either remove this custom page fixture and export test = base directly, or
implement the intended customization (e.g., automatic auth injection, additional
setup/teardown) inside the page fixture and add a short inline comment
explaining the purpose; locate and update the test constant and the page fixture
implementation to apply one of these two changes.
- Around line 41-44: No logout selector should rely on fragile text; in the
logout function replace the page.click('text=Sair') use a robust selector such
as page.getByRole('button', { name: /sair/i }) or a stable data-testid (e.g.
page.getByTestId('logout-button')) so the click targets the logout button by
role/aria or test id; update the logout(Page) implementation to use that
selector (and ensure the app exposes the matching aria-label or data-testid) and
keep the existing await page.waitForURL(...) as is.
- Around line 17-23: The current silent .catch() on page.waitForURL in
loginAsAdmin (and the same pattern in loginAsProvider and loginAsCustomer) masks
real failures; update each login helper to explicitly handle Playwright
TimeoutError vs other exceptions: call page.waitForURL(...) inside a try/catch,
and in the catch inspect error.name or error.message (e.g., "TimeoutError") to
treat only expected timeouts as the mock/test-mode case (log a specific message)
while rethrowing or failing-fast for any other errors (navigation failures,
element-not-found, etc.), and consider splitting the click and wait steps so
element-not-found errors can be caught and reported separately.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.ts`:
- Line 1: The imports loginAsCustomer and logout are unused in the test suite;
remove them from the import statement (the line that currently imports test,
expect, loginAsCustomer, logout from '@meajudaai/web-e2e-support') so only
needed symbols (test, expect) are imported, or alternatively use those functions
in an authentication test if intended—update the import to eliminate the unused
identifiers to fix the lint/cleanup warning.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e1a2ee71-f29b-4085-9312-fd8716f54c37
⛔ Files ignored due to path filters (2)
src/Web/MeAjudaAi.Web.Provider/e2e/auth.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**src/Web/MeAjudaAi.Web.Provider/e2e/onboarding.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**
📒 Files selected for processing (14)
.github/workflows/master-ci-cd.yml.gitignoredocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdsrc/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/search.spec.tssrc/Web/libs/e2e-support/base.tssrc/Web/libs/e2e-support/project.jsonsrc/Web/libs/e2e-support/tsconfig.jsonsrc/Web/libs/e2e-support/tsconfig.lib.jsonsrc/Web/playwright.config.ts
✅ Files skipped from review due to trivial changes (2)
- .gitignore
- src/Web/libs/e2e-support/tsconfig.lib.json
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/architecture.md (1)
3212-3236:⚠️ Potential issue | 🟠 MajorSeção “Estrutura de Arquivos (React)” contém bloco C#/bUnit indevido.
As linhas exibem código de teste Blazor (
RenderComponent,Mud...) dentro da documentação React, quebrando o contexto da seção.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 3212 - 3236, Remove the misplaced C#/bUnit test block (the RenderComponent<Providers>() usages, _mockDispatcher.Verify, Providers_Should_Display_Loading_State test, and Mud progress references like ".mud-progress-circular") from the “Estrutura de Arquivos (React)” section and either move it to the Blazor/Tests documentation or replace it with the correct React file-structure example and React-specific snippets for Providers; ensure references to RenderComponent, _mockDispatcher, Providers_Should_Display_Loading_State, and Mud classes are not left in the React section.docs/admin-portal/overview.md (1)
129-130:⚠️ Potential issue | 🟠 MajorAtualizar URIs de Redirect para NextAuth + Keycloak.
Os URIs documentados
/authentication/login-callbacke/authentication/logout-callbackcorrespondem a uma implementação anterior (Blazor WASM). A implementação atual utiliza NextAuth.js v4, que usa callbacks padrão em/api/auth/callback/[provider]. Para Keycloak, o URI correto deve ser:
https://localhost:7001/api/auth/callback/keycloakAtualize a documentação para refletir a configuração real do NextAuth e não as rotas da implementação anterior.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 129 - 130, Replace the outdated Blazor WASM redirect URIs `/authentication/login-callback` and `/authentication/logout-callback` with the NextAuth callback pattern `/api/auth/callback/[provider]` and specifically update to `https://localhost:7001/api/auth/callback/keycloak`; ensure the docs mention NextAuth.js v4 and that the provider segment is `keycloak` so readers configure Keycloak redirects correctly.
♻️ Duplicate comments (3)
docs/admin-portal/overview.md (1)
68-100:⚠️ Potential issue | 🟠 MajorAjustar paths para refletir o layout real do workspace.
A seção mistura
apps/admin-portal/com uma organização que, no restante da documentação, aparece sobsrc/Web/.... Isso tende a confundir setup e navegação.#!/bin/bash # Verifica quais caminhos existem de fato no repositório fd -td 'admin-portal$|MeAjudaAi\.Web\.Admin$' fd -tf '^playwright\.config\.ts$' fd -td '^MeAjudaAi\.Web\..*\.Tests$' tests src/WebAlso applies to: 104-114
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 68 - 100, The docs tree under apps/admin-portal/ is inconsistent with the actual workspace layout (which uses src/Web/...); update the overview to reflect the real directories and filenames used in the repo by replacing references to apps/admin-portal/ and its child folders with the corresponding src/Web/... structure used elsewhere in the docs (ensure entries for the App Router, components, hooks, stores, lib, and types match the real module names such as the Web Admin app folder and any actual folder names like MeAjudaAi.Web.Admin or similar), and make the same corrections in the repeated section around lines 104-114 so all path examples point to the canonical workspace layout used across the docs.docs/architecture.md (1)
3254-3255:⚠️ Potential issue | 🟠 MajorCorrigir
testDirdocumentado do Playwright.A documentação diz
testDir: './tests', mas osrc/Web/playwright.config.tsatual usatestDir: './src'.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 3254 - 3255, A documentação está desatualizada: atualize a referência de testDir no documento para casar com a configuração atual do Playwright; altere a entrada documentada de testDir de './tests' para './src' (ou, se preferir manter './tests', atualize o Playwright config em playwright.config.ts para usar './tests'), verificando a chave testDir na configuração do Playwright para garantir consistência entre docs e código.src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts (1)
26-33:⚠️ Potential issue | 🟡 MinorFortaleça a validação do filtro para evitar falso-positivo.
Aqui ainda há o mesmo problema de critério fraco: somente
toBeVisible()não garante que o filtro “Ativos” foi aplicado de fato.💡 Ajuste sugerido
test('should filter by status', async ({ page }) => { await page.click('button:has-text("Filtrar")'); await page.click('text=Ativos'); - // Verify filtered results are visible + // Verify filtered results match the selected status const providerRows = page.locator('[data-testid="provider-row"]'); await expect(providerRows.first()).toBeVisible(); + const rowTexts = await providerRows.allTextContents(); + expect(rowTexts.length).toBeGreaterThan(0); + expect(rowTexts.every((text) => /\bativo(s)?\b/i.test(text))).toBeTruthy(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts` around lines 26 - 33, The test 'should filter by status' currently only checks visibility which can give false-positives; update the assertion using the existing providerRows locator to verify the filter actually applied by asserting each visible row's status cell contains the expected "Ativos"/"Ativo" text (e.g., locate status within providerRows via a status selector like provider-row >> [data-testid="provider-status"] or similar) or assert the list length matches an expected filtered count; replace the single toBeVisible() check with a stronger expectation using toHaveCount()/toContainText() or iterate through providerRows and assert textContent for the status.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/admin-portal/overview.md`:
- Line 119: Remove the stray closing Markdown code fence at the end of the code
block (the lone "```" shown) so the code block is properly balanced; locate the
unmatched closing fence in the overview.md around the end of the example and
delete it (or add a matching opening fence if the intention was to start a new
block), then preview the markdown to confirm subsequent sections render
correctly.
In `@docs/architecture.md`:
- Around line 3183-3202: The provided Playwright test uses email/password login
but the project e2e helper (src/Web/libs/e2e-support/base.ts) expects an OAuth
flow via the Keycloak button; update the test in Providers Management to perform
the OAuth login flow: replace the direct page.fill calls and click on
'[data-testid="login-button"]' with the Keycloak-triggering action (click the
Keycloak login button used by the shared helper) and then await the
redirect/validation logic provided by the e2e support (reuse the same
await/validation pattern from the e2e-support base helper), ensuring the test
still navigates to '/admin/providers' and asserts
'[data-testid="providers-table"]' visibility.
- Around line 2897-2903: The hook useProviders currently uses the removed
keepPreviousData option; update the useQuery options to use placeholderData
instead: import keepPreviousData from '@tanstack/react-query' and set
placeholderData: keepPreviousData, or use placeholderData: (previousData) =>
previousData; adjust the return in useProviders (and keep the existing queryKey
and queryFn that call providersApi.getProviders) so TanStack Query v5 preserves
previous page data correctly.
In `@docs/roadmap-current.md`:
- Line 630: The CI note under "7. **CI Integration**" contains a Spanish word
"pendiente" and should be changed to Portuguese pt-BR; update the text in the
docs/roadmap-current.md entry for "7. **CI Integration**" replacing "pendiente"
with "pendente" and scan the same sentence referencing `pr-validation.yml`,
`master-ci-cd.yml` and `RUN_E2E='true'` to ensure all other words use pt-BR
spelling consistently.
- Line 610: Update the checklist item that currently reads "✅ **Admin Portal
React**: Functional `apps/admin-portal`" to reference the correct Admin Portal
location by replacing `apps/admin-portal` with `src/Web/MeAjudaAi.Web.Admin/` so
the roadmap points to the existing React admin project (match the style used for
Customer/Provider entries).
In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts`:
- Around line 46-55: The test "should approve document" uses non-existent
selectors (data-testid="document-approve"/"document-reject") and only asserts an
alert; update the flow to open the provider detail and assert state change:
navigate to '/admin/documentos', click the first provider's "eye" icon (use the
visual/icon locator used elsewhere in the app to open details), click the
visible "Aprovar" button in the detail view, assert success alert appears,
assert you return to the listing, and finally assert that the provider no longer
appears in the pending list; alternatively if approval must happen from the
list, add proper data-testid attributes to the list buttons and update the
selectors in the test (referencing the test name and the Eye/detail view and the
"Aprovar" button to locate code changes).
---
Outside diff comments:
In `@docs/admin-portal/overview.md`:
- Around line 129-130: Replace the outdated Blazor WASM redirect URIs
`/authentication/login-callback` and `/authentication/logout-callback` with the
NextAuth callback pattern `/api/auth/callback/[provider]` and specifically
update to `https://localhost:7001/api/auth/callback/keycloak`; ensure the docs
mention NextAuth.js v4 and that the provider segment is `keycloak` so readers
configure Keycloak redirects correctly.
In `@docs/architecture.md`:
- Around line 3212-3236: Remove the misplaced C#/bUnit test block (the
RenderComponent<Providers>() usages, _mockDispatcher.Verify,
Providers_Should_Display_Loading_State test, and Mud progress references like
".mud-progress-circular") from the “Estrutura de Arquivos (React)” section and
either move it to the Blazor/Tests documentation or replace it with the correct
React file-structure example and React-specific snippets for Providers; ensure
references to RenderComponent, _mockDispatcher,
Providers_Should_Display_Loading_State, and Mud classes are not left in the
React section.
---
Duplicate comments:
In `@docs/admin-portal/overview.md`:
- Around line 68-100: The docs tree under apps/admin-portal/ is inconsistent
with the actual workspace layout (which uses src/Web/...); update the overview
to reflect the real directories and filenames used in the repo by replacing
references to apps/admin-portal/ and its child folders with the corresponding
src/Web/... structure used elsewhere in the docs (ensure entries for the App
Router, components, hooks, stores, lib, and types match the real module names
such as the Web Admin app folder and any actual folder names like
MeAjudaAi.Web.Admin or similar), and make the same corrections in the repeated
section around lines 104-114 so all path examples point to the canonical
workspace layout used across the docs.
In `@docs/architecture.md`:
- Around line 3254-3255: A documentação está desatualizada: atualize a
referência de testDir no documento para casar com a configuração atual do
Playwright; altere a entrada documentada de testDir de './tests' para './src'
(ou, se preferir manter './tests', atualize o Playwright config em
playwright.config.ts para usar './tests'), verificando a chave testDir na
configuração do Playwright para garantir consistência entre docs e código.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts`:
- Around line 26-33: The test 'should filter by status' currently only checks
visibility which can give false-positives; update the assertion using the
existing providerRows locator to verify the filter actually applied by asserting
each visible row's status cell contains the expected "Ativos"/"Ativo" text
(e.g., locate status within providerRows via a status selector like provider-row
>> [data-testid="provider-status"] or similar) or assert the list length matches
an expected filtered count; replace the single toBeVisible() check with a
stronger expectation using toHaveCount()/toContainText() or iterate through
providerRows and assert textContent for the status.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d8e0f175-c3da-4844-b7e3-607d98acc55a
⛔ Files ignored due to path filters (2)
src/Web/MeAjudaAi.Web.Provider/e2e/auth.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**src/Web/MeAjudaAi.Web.Provider/e2e/onboarding.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**
📒 Files selected for processing (15)
.github/workflows/master-ci-cd.yml.gitignoredocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdsrc/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/search.spec.tssrc/Web/libs/e2e-support/.eslintrc.jsonsrc/Web/libs/e2e-support/base.tssrc/Web/libs/e2e-support/project.jsonsrc/Web/libs/e2e-support/tsconfig.jsonsrc/Web/libs/e2e-support/tsconfig.lib.jsonsrc/Web/playwright.config.ts
✅ Files skipped from review due to trivial changes (9)
- .gitignore
- src/Web/libs/e2e-support/tsconfig.lib.json
- src/Web/libs/e2e-support/tsconfig.json
- src/Web/libs/e2e-support/.eslintrc.json
- src/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.ts
- src/Web/MeAjudaAi.Web.Customer/e2e/search.spec.ts
- src/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.ts
- src/Web/playwright.config.ts
- src/Web/libs/e2e-support/base.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/Web/libs/e2e-support/project.json
- .github/workflows/master-ci-cd.yml
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/architecture.md (1)
2891-3010:⚠️ Potential issue | 🟠 MajorRemover seção Refit da documentação de Frontend React.
A seção "TanStack Query - Data Fetching Patterns" (linhas 2917-3008) documenta o SDK .NET Refit (biblioteca C# para clientes HTTP tipados), mas está inserida dentro do capítulo "Frontend Architecture (Sprint 6+)" que descreve React + Next.js + TanStack Query.
Problemas identificados:
- Incompatibilidade tecnológica: Refit é exclusivo do ecossistema .NET/C# e não pode ser usado em aplicações React/TypeScript/Node.js (conforme já documentado em comentário anterior sobre a linha 3038)
- Contexto incorreto: Todo o conteúdo desta seção (interfaces
IProvidersApi,IDocumentsApi, configuração comAddRefitClient, etc.) é código C# para clientes .NET, não React- Referência confusa: A linha 3009 menciona
src/Web/MeAjudaAi.Web.Customer/types/README.md, sugerindo tipos TypeScript, mas todo o conteúdo precedente é C#Ação recomendada:
Mover esta seção para um capítulo apropriado sobre ".NET Client SDK" ou "Backend Integration" e substituir por documentação de como consumir a API em React/TypeScript usando:
- Fetch API nativo do Next.js
- TanStack Query hooks (
useQuery,useMutation)- Tipos TypeScript gerados via OpenAPI (
types/api/generated/)📋 Estrutura sugerida para substituição
### **TanStack Query - Data Fetching Patterns** **Consumo de API em React/TypeScript**: ```typescript // 1. Tipos gerados automaticamente via OpenAPI import type { ModuleProviderDto, PagedResult } from '@/types/api/generated'; // 2. API client wrapper async function getProviders(params: { pageNumber: number; pageSize: number }) { const response = await fetch(`/api/v1/providers?pageNumber=${params.pageNumber}&pageSize=${params.pageSize}`); if (!response.ok) throw new Error('Failed to fetch providers'); return response.json() as Promise<PagedResult<ModuleProviderDto>>; } // 3. TanStack Query hook export function useProviders(page: number = 1) { return useQuery({ queryKey: ['providers', page], queryFn: () => getProviders({ pageNumber: page, pageSize: 20 }), staleTime: 30 * 1000, }); } // 4. Uso em componente React export function ProvidersList() { const { data, isLoading, error } = useProviders(); if (isLoading) return <Spinner />; if (error) return <ErrorMessage error={error} />; return <DataGrid data={data.items} />; }Nota: Para clientes .NET (Blazor, console apps, etc.), consulte a documentação do SDK Refit em
docs/backend/client-sdk.md.</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against the current code and only fix it if needed.
In
@docs/architecture.mdaround lines 2891 - 3010, The Refit (.NET) content
(interfaces like IProvidersApi, IDocumentsApi, IServiceCatalogsApi and the
AddRefitClient registration) is misplaced in the Frontend React chapter; move
that entire Refit section to a backend or ".NET Client SDK" chapter (e.g.,
docs/backend/client-sdk.md) and replace it here with React/TypeScript
instructions: document using TypeScript types from types/api/generated, an API
wrapper function (e.g., getProviders), and TanStack Query hooks (useProviders,
useCreateProvider) that call that wrapper; also update the reference at the end
to point to the new .NET SDK doc instead of
src/Web/MeAjudaAi.Web.Customer/types/README.md.</details> </blockquote></details> <details> <summary>docs/roadmap-current.md (1)</summary><blockquote> `669-676`: _⚠️ Potential issue_ | _🟡 Minor_ **Atualizar conteúdo do Risk Scenario 3 para refletir migração React.** O título foi atualizado para "React Performance Issues", mas o conteúdo ainda referencia mitigações específicas de Blazor WebAssembly ("lazy loading de assemblies", "AOT compilation", "bundle size"). Para React/Next.js, as mitigações apropriadas seriam: - Code splitting com dynamic imports - Tree shaking e otimização de bundle - SSR/SSG com Next.js para melhorar carregamento inicial - Lazy loading de componentes React - Otimização de imagens com next/image <details> <summary>♻️ Sugestão de conteúdo corrigido</summary> ```diff ### Risk Scenario 3: React Performance Issues -- **Problema Potencial**: App bundle size > 5MB, lazy loading não configurado corretamente +- **Problema Potencial**: Bundle size excessivo (> 500KB inicial), code splitting inadequado - **Impacto**: UX ruim, +2-3 dias de otimização - **Mitigação Sprint 9**: - - Implementar lazy loading de assemblies - - Otimizar bundle size (tree shaking, AOT compilation) + - Implementar code splitting com dynamic imports + - Otimizar bundle size (tree shaking, minificação) + - Configurar SSR/SSG com Next.js para carregamento inicial rápido - Adicionar loading indicators e progressive loading🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap-current.md` around lines 669 - 676, Update "Risk Scenario 3: React Performance Issues" to remove Blazor-specific mitigations ("Implementar lazy loading de assemblies", "AOT compilation") and replace them with React/Next.js appropriate actions: list "Code splitting with dynamic imports", "Tree shaking and bundle optimization", "SSR/SSG via Next.js to improve initial load", "Lazy load React components", and "Optimize images using next/image and responsive formats"; ensure the mitigation bullet list under "Mitigação Sprint 9" uses these React/Next.js terms and preserves impact and timeframe language.
🧹 Nitpick comments (3)
src/Web/libs/e2e-support/base.ts (3)
13-23: Considere verificar o estado pós-login para maior confiabilidade dos testes.O tratamento atual do
TimeoutErrorfunciona, mas não distingue entre:
- Modo mock funcionando corretamente (timeout esperado)
- Modo real com falha no redirect (timeout inesperado)
Isso pode causar testes flaky que passam silenciosamente mesmo quando o login falhou.
♻️ Sugestão de melhoria
+import { test as base, Page, TimeoutError } from '@playwright/test'; -import { test as base, Page } from '@playwright/test'; async function handleLoginRedirect(page: Page): Promise<void> { try { await page.waitForURL(/.*keycloak.*|.*realms.*\/meajudaai/i, { timeout: 5000 }); } catch (error) { - if (error instanceof Error && error.name === 'TimeoutError') { + if (error instanceof TimeoutError) { console.log('OAuth redirect intercepted - running in mock/test mode'); + // Verifica se ainda estamos em uma página válida da aplicação + const currentUrl = page.url(); + if (!currentUrl.includes('/login') && !currentUrl.includes('/admin') && !currentUrl.includes('/provider')) { + throw new Error(`Login redirect failed: unexpected URL ${currentUrl}`); + } } else { throw error; } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 13 - 23, handleLoginRedirect currently treats a TimeoutError as a benign mock-mode signal which can hide real login failures; modify handleLoginRedirect(Page) to, after a timeout from page.waitForURL, perform a deterministic post-login verification (e.g., check for a known logged-in selector like a user avatar or logout button, or verify a session cookie/token) and only swallow the timeout if that verification proves mock-mode login is present, otherwise rethrow or fail the test; reference the existing waitForURL call and add a follow-up check (selector existence or cookie via page.context().cookies()) to decide whether to treat the timeout as expected.
25-41: Considere aguardar o carregamento da página antes de interagir.As funções de login navegam e clicam imediatamente. Em conexões lentas ou builds de CI, o botão pode não estar interativo ainda.
♻️ Sugestão para maior robustez
export async function loginAsAdmin(page: Page): Promise<void> { - await page.goto('/admin/login'); + await page.goto('/admin/login', { waitUntil: 'networkidle' }); await page.getByRole('button', { name: /entrar com keycloak/i }).click(); await handleLoginRedirect(page); }Aplique o mesmo padrão para
loginAsProvidereloginAsCustomer.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 25 - 41, The login helpers (loginAsAdmin, loginAsProvider, loginAsCustomer) navigate then click immediately which can fail on slow CI; before clicking await the page to be ready and the button to be visible/interactive (e.g., wait for load state and/or wait for the role-based locator to be visible/enabled) and then perform the click, keeping the existing call to handleLoginRedirect; apply this same wait pattern to all three functions so each waits for the target button (via page.getByRole(...)) to be ready before clicking.
43-46: Adicione timeout explícito e tratamento defensivo.A função
logoutnão especifica timeout parawaitForURL, o que pode causar testes que ficam pendurados por muito tempo em caso de falha. Além disso, não há garantia de que o botão "Sair" está visível antes do clique.♻️ Sugestão de melhoria
export async function logout(page: Page): Promise<void> { + const logoutButton = page.getByRole('button', { name: /sair/i }); + await logoutButton.waitFor({ state: 'visible', timeout: 5000 }); - await page.getByRole('button', { name: /sair/i }).click(); + await logoutButton.click(); - await page.waitForURL(/\/(login|admin\/login|provider\/login)/); + await page.waitForURL(/\/(login|admin\/login|provider\/login)/, { timeout: 10000 }); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 43 - 46, The logout function should defensively ensure the "Sair" button is visible before clicking and use explicit timeouts for waiting so tests don't hang: update export async function logout(page: Page) to await a visibility/waitForSelector or page.getByRole(...).waitFor({ state: 'visible', timeout: <reasonable-ms> }) (or assert isVisible) before calling click, call page.waitForURL(/\/(login|admin\/login|provider\/login)/, { timeout: <reasonable-ms> }), and wrap the sequence in a try/catch to surface a clear error message if visibility/click or the URL wait fails; reference the logout function, Page, page.getByRole('button', { name: /sair/i }) and page.waitForURL to locate where to apply these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@docs/architecture.md`:
- Around line 2891-3010: The Refit (.NET) content (interfaces like
IProvidersApi, IDocumentsApi, IServiceCatalogsApi and the AddRefitClient
registration) is misplaced in the Frontend React chapter; move that entire Refit
section to a backend or ".NET Client SDK" chapter (e.g.,
docs/backend/client-sdk.md) and replace it here with React/TypeScript
instructions: document using TypeScript types from types/api/generated, an API
wrapper function (e.g., getProviders), and TanStack Query hooks (useProviders,
useCreateProvider) that call that wrapper; also update the reference at the end
to point to the new .NET SDK doc instead of
src/Web/MeAjudaAi.Web.Customer/types/README.md.
In `@docs/roadmap-current.md`:
- Around line 669-676: Update "Risk Scenario 3: React Performance Issues" to
remove Blazor-specific mitigations ("Implementar lazy loading de assemblies",
"AOT compilation") and replace them with React/Next.js appropriate actions: list
"Code splitting with dynamic imports", "Tree shaking and bundle optimization",
"SSR/SSG via Next.js to improve initial load", "Lazy load React components", and
"Optimize images using next/image and responsive formats"; ensure the mitigation
bullet list under "Mitigação Sprint 9" uses these React/Next.js terms and
preserves impact and timeframe language.
---
Nitpick comments:
In `@src/Web/libs/e2e-support/base.ts`:
- Around line 13-23: handleLoginRedirect currently treats a TimeoutError as a
benign mock-mode signal which can hide real login failures; modify
handleLoginRedirect(Page) to, after a timeout from page.waitForURL, perform a
deterministic post-login verification (e.g., check for a known logged-in
selector like a user avatar or logout button, or verify a session cookie/token)
and only swallow the timeout if that verification proves mock-mode login is
present, otherwise rethrow or fail the test; reference the existing waitForURL
call and add a follow-up check (selector existence or cookie via
page.context().cookies()) to decide whether to treat the timeout as expected.
- Around line 25-41: The login helpers (loginAsAdmin, loginAsProvider,
loginAsCustomer) navigate then click immediately which can fail on slow CI;
before clicking await the page to be ready and the button to be
visible/interactive (e.g., wait for load state and/or wait for the role-based
locator to be visible/enabled) and then perform the click, keeping the existing
call to handleLoginRedirect; apply this same wait pattern to all three functions
so each waits for the target button (via page.getByRole(...)) to be ready before
clicking.
- Around line 43-46: The logout function should defensively ensure the "Sair"
button is visible before clicking and use explicit timeouts for waiting so tests
don't hang: update export async function logout(page: Page) to await a
visibility/waitForSelector or page.getByRole(...).waitFor({ state: 'visible',
timeout: <reasonable-ms> }) (or assert isVisible) before calling click, call
page.waitForURL(/\/(login|admin\/login|provider\/login)/, { timeout:
<reasonable-ms> }), and wrap the sequence in a try/catch to surface a clear
error message if visibility/click or the URL wait fails; reference the logout
function, Page, page.getByRole('button', { name: /sair/i }) and page.waitForURL
to locate where to apply these changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 75264e5e-1cab-4b0a-92d7-326c633d4147
⛔ Files ignored due to path filters (2)
src/Web/MeAjudaAi.Web.Provider/e2e/auth.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**src/Web/MeAjudaAi.Web.Provider/e2e/onboarding.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**
📒 Files selected for processing (15)
.github/workflows/master-ci-cd.yml.gitignoredocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdsrc/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/search.spec.tssrc/Web/libs/e2e-support/.eslintrc.jsonsrc/Web/libs/e2e-support/base.tssrc/Web/libs/e2e-support/project.jsonsrc/Web/libs/e2e-support/tsconfig.jsonsrc/Web/libs/e2e-support/tsconfig.lib.jsonsrc/Web/playwright.config.ts
✅ Files skipped from review due to trivial changes (9)
- src/Web/libs/e2e-support/.eslintrc.json
- .gitignore
- src/Web/libs/e2e-support/tsconfig.json
- src/Web/libs/e2e-support/tsconfig.lib.json
- src/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.ts
- src/Web/libs/e2e-support/project.json
- src/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.ts
- src/Web/MeAjudaAi.Web.Customer/e2e/search.spec.ts
- src/Web/playwright.config.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts
- .github/workflows/master-ci-cd.yml
…ations, and performance across customer, provider, and admin applications.
There was a problem hiding this comment.
Actionable comments posted: 17
♻️ Duplicate comments (1)
src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts (1)
9-11:⚠️ Potential issue | 🔴 CriticalAdicione
data-testidaos componentes para que os testes possam localizá-los.O teste na linha 10 busca por
[data-testid="providers-table"], mas o componente emproviders/page.tsxrenderiza<table className="w-full">sem esse atributo. O mesmo ocorre com todos os outrosdata-testidusados no arquivo de testes:provider-row,provider-status,documents-list,provider-detail,approve-buttoneview-details. Sem esses atributos, todos os testes falharão com timeout.Adicione os
data-testidcorrespondentes aos elementos no componente ou atualize os seletores para usar alternativas existentes (ex:table,tbody tr,aria-label, roles).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts` around lines 9 - 11, The tests expect data-testid attributes that don't exist: update the providers page component (providers/page.tsx) and the related provider row/detail elements to include data-testid="providers-table", data-testid="provider-row", data-testid="provider-status", data-testid="documents-list", data-testid="provider-detail", data-testid="approve-button" and data-testid="view-details" on the corresponding <table>, row, status cell, documents list, detail panel and action buttons (or if you prefer not to add attributes, change the tests to use existing selectors such as table, tbody tr, aria-label values or role-based queries); ensure the exact testid strings match those used in the spec so the locators in the test (providers.spec.ts) can find the elements.
🧹 Nitpick comments (4)
src/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.ts (1)
1-1: Imports não utilizados.
loginAsCustomerelogoutsão importados mas não são usados neste arquivo de teste. Remova-os para manter o código limpo.♻️ Correção sugerida
-import { test, expect, loginAsCustomer, logout } from '@meajudaai/web-e2e-support'; +import { test, expect } from '@meajudaai/web-e2e-support';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.ts` at line 1, The import statement in onboarding.spec.ts includes unused symbols loginAsCustomer and logout; remove these unused imports from the import declaration so it only imports the actually used symbols (test, expect) to clean up the file and avoid linter warnings.src/Web/libs/e2e-support/base.ts (1)
43-46:logoutnão verifica se o usuário está logado antes de clicar.Se chamado quando o usuário já está deslogado, o teste falhará com erro de timeout pouco informativo ao tentar clicar no botão "Sair".
♻️ Melhoria sugerida
export async function logout(page: Page): Promise<void> { + const logoutButton = page.getByRole('button', { name: /sair/i }); + if (!(await logoutButton.isVisible({ timeout: 2000 }).catch(() => false))) { + console.log('Logout skipped - user not logged in'); + return; + } - await page.getByRole('button', { name: /sair/i }).click(); + await logoutButton.click(); await page.waitForURL(/\/(login|admin\/login|provider\/login)/); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/libs/e2e-support/base.ts` around lines 43 - 46, A função logout tenta clicar no botão "Sair" sem verificar se ele existe, causando timeout se o usuário já estiver deslogado; modifique logout (exported function logout(page: Page)) para primeiro localizar o botão via page.locator or page.getByRole (name: /sair/i) e checar presença/visibilidade (ex.: count()>0 ou isVisible()) antes de clicar, só executar o click e o await page.waitForURL(...) quando o botão existir; se não existir, retorne imediatamente para evitar falha do teste.src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts (1)
182-183: Asserção de lazy loading pode ser muito restritiva.A asserção
expect(lazyLoadedImages.length).toBeGreaterThan(0)falhará se a homepage não tiver imagens comloading="lazy". Imagens above-the-fold não devem usar lazy loading (prejudica LCP). Considere tornar isso condicional ou verificar apenas se imagens below-the-fold usam lazy.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts` around lines 182 - 183, The current assertion uses lazyLoadedImages and will fail if there are no lazy images above the fold; update the check to only assert lazy loading for images below the fold by computing viewport height (e.g., window.innerHeight or document.documentElement.clientHeight), filter imagesWithSrc by element.getBoundingClientRect().top > viewportHeight to get imagesBelowFold, then either assert that every image in imagesBelowFold has loading === 'lazy' or make the assertion conditional (only run expect when imagesBelowFold.length > 0). Reference the existing variables lazyLoadedImages and imagesWithSrc and replace the current expect line with the conditional/below-the-fold-based assertion.src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts (1)
30-31: EvitewaitForTimeout- anti-pattern de testes flaky.
waitForTimeout(500)é um "magic sleep" que pode causar testes flaky. Use esperas explícitas baseadas em condições reais.♻️ Correção sugerida
- // Wait for filter to apply - await page.waitForTimeout(500); + // Wait for filter to apply by checking URL or network idle + await page.waitForLoadState('networkidle');🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts` around lines 30 - 31, The test uses a brittle fixed sleep via page.waitForTimeout(500); replace this magic wait with an explicit wait that reflects the real condition: e.g., wait for the filter result element or network response instead. Locate the usage of page.waitForTimeout in providers.spec.ts and change it to an appropriate explicit wait such as locator.waitFor({ state: 'visible' }) on the element that indicates the filter has applied (or page.waitForResponse matching the filter request) so the test only proceeds once the UI or network state is ready.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/admin-portal/overview.md`:
- Line 234: Substitua a frase mista em inglês/português "Os testes exercising
the OAuth flow via Keycloak (signIn(\"keycloak\")) em vez de formulários de
email/password" por uma versão totalmente em pt-BR, p.ex. "Os testes exercitam o
fluxo OAuth via Keycloak (signIn('keycloak')) em vez de formulários de
email/senha"; mantenha a referência ao método signIn("keycloak") intacta e
ajuste "email/password" para "email/senha" para consistência editorial.
- Around line 102-110: O documento contém caminhos E2E conflitantes:
`src/Web/MeAjudaAi.Web.Admin/e2e/` e `tests/MeAjudaAi.Web.Admin.Tests/e2e/`;
pick one canonical path and update all occurrences to match it (including the
listing at `src/Web/MeAjudaAi.Web.Admin/ └── e2e/` and the entries around lines
233–234 that reference `tests/MeAjudaAi.Web.Admin.Tests/e2e/`), ensuring
examples, tree structures and any prose consistently reference the chosen
directory (`src/Web/MeAjudaAi.Web.Admin/e2e/` or
`tests/MeAjudaAi.Web.Admin.Tests/e2e/`) so the document no longer contains
contradictory paths.
In `@docs/architecture.md`:
- Around line 3236-3250: The fenced code block that begins with "src/Web/" is
missing a language tag which triggers markdownlint MD040; update the opening
fence from ``` to ```text so the block is explicitly marked as text (modify the
code block starting with the "src/Web/" listing in the architecture.md content).
- Around line 3205-3250: The docs disagree on the canonical E2E test location
(architecture.md uses src/Web/MeAjudaAi.Web.Admin/e2e while other docs use
tests/MeAjudaAi.Web.*.Tests/e2e); pick the canonical path (e.g., standardize on
tests/MeAjudaAi.Web.*.Tests/e2e), update the entry in the React file tree and
the Playwright bullet in architecture.md to that path, and update any other docs
(e.g., docs/admin-portal/overview.md and docs/roadmap-current.md) so all
references match; also ensure the Playwright config note (testDir) aligns with
the chosen path so users get correct setup/exec instructions.
In `@docs/roadmap-current.md`:
- Around line 617-621: Unifique o significado da Sprint 8E em todo o documento:
escolha a definição correta (por exemplo "Sprint 8E - E2E Tests React Apps
(Playwright)" ou "Sprint 8E (Mobile)") e atualize todas as ocorrências para essa
mesma descrição; especificamente, alinhe o cabeçalho "### ⏳ Sprint 8E - E2E
Tests React Apps (Playwright) (23 Mar - 4 Abr 2026)" com outras menções como
"Sprint 8E (Mobile)" para evitar conflito de escopo e datas, garantindo que
títulos, subtítulos e quaisquer referências de escopo/dateline usem o mesmo
texto e contexto.
- Around line 35-40: O roadmap declara o "Admin Portal" como "React (migrado
Sprint 8D)" com a stack listada (React 19 + TypeScript 5.7+, Tailwind CSS v4,
Zustand, React Hook Form + Zod) mas há referências conflitantes a Blazor em
outras seções; abra o documento e unifique o estado atual removendo ou
atualizando qualquer ocorrência de "Admin" associada a Blazor e padronize a
entrada para "Admin Portal — React (migrado Sprint 8D)" com a stack completa
mencionada para garantir consistência em todo o arquivo.
In `@src/Web/libs/e2e-support/base.ts`:
- Around line 13-23: handleLoginRedirect currently swallows a TimeoutError from
page.waitForURL and treats it as success; change it so when a TimeoutError is
caught you validate a post-login state (for example check page.url() or
waitForSelector of a known logged-in element) and only return silently if that
validation confirms a logged-in/session state, otherwise rethrow or throw a
descriptive error; keep references to handleLoginRedirect, page.waitForURL and
the TimeoutError branch when implementing the additional check.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/configs.spec.ts`:
- Around line 9-11: O teste em configs.spec.ts usa data-testid="cities-list",
"city-row" e "city-form" que não existem na UI; abra o componente
allowed-cities/page.tsx e ou (a) adicione esses atributos aos elementos
correspondentes (lista de cidades, linha de cidade e formulário de cidade) ou
(b) atualize configs.spec.ts para selecionar elementos já presentes na DOM (por
exemplo classes ou IDs atuais), garantindo que os seletores em configs.spec.ts
correspondam exatamente aos nomes dos elementos em allowed-cities/page.tsx.
- Around line 74-77: The test is filling non-existent form fields; update the
selectors to match services/page.tsx by replacing 'input[name="serviceName"]'
with 'input[name="name"]', remove the 'input[name="basePrice"]' fill entirely,
and instead interact with the category field (e.g., use
'select[name="categoryId"]' or the appropriate category input) before clicking
the "Salvar" button so the test fills only the actual fields: name, description
and categoryId.
- Around line 17-19: O teste está usando nomes de campo incorretos; atualize as
chamadas em configs.spec.ts para preencher os nomes corretos conforme
allowed-cities/page.tsx: substituir page.fill('input[name="cityName"]', ...) por
page.fill('input[name="city"]', ...), e substituir
page.fill('input[name="maxProviders"]', ...) por
page.fill('input[name="serviceRadiusKm"]', ...); mantenha o preenchimento do
campo 'state' conforme está.
- Around line 137-146: Os testes "should display general settings" e "should
update platform settings" usam seletores inexistentes
(data-testid="general-settings" e input[name="platformFee"]); atualize-os para
usar os elementos reais da UI — por exemplo, para verificar a aba de perfil use
um locator que procura pelo texto/aba "Perfil" ou pelos campos existentes
input[name="adminName"] e input[name="adminEmail"], e na atualização de
configurações preencha esses campos em vez de platformFee e verifique a mensagem
de sucesso; ajuste os nomes dos testes/selets para refletir "profile settings"
quando alterar os comportamentos em test('should display general settings') e
test('should update platform settings') para localizar e interagir com
adminName/adminEmail ou as tabs reais.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts`:
- Around line 79-80: O selector page.getByRole('alert') não funciona para toasts
do Sonner; substitua todas as ocorrências de page.getByRole('alert') (por
exemplo na asserção await
expect(page.getByRole('alert')).toContainText(/aprova/i) e na outra asserção de
rejeição) por page.getByRole('status') para corretamente localizar o container
do toast e validar o texto.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.ts`:
- Line 34: The selector used in the assertion is case-sensitive and may fail if
the UI capitalizes the message; update the locator used in the assertion (the
page.locator(...) passed into expect(...).toBeVisible()) to use a
case-insensitive text match (e.g., a regex text selector with the i flag) so
"email inválido" and "Email inválido" both match.
- Around line 82-88: O fluxo completo dentro do bloco que verifica
page.locator('input[name="cep"]').isVisible() omite o preenchimento dos campos
'city' e 'state' (preenchidos no teste isolado), o que pode causar falhas
intermitentes; ajuste o bloco que usa page.fill('input[name="cep"]', ...),
page.fill('input[name="street"]', ...), etc. para também preencher
page.fill('input[name="city"]', '<cidade>') e page.fill('input[name="state"]',
'<estado>') antes de clicar em page.click('button:has-text("Próximo")'),
mantendo os mesmos valores usados no teste isolado e respeitando a checagem de
visibilidade com page.locator.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 49-72: The two tests inside the test.describe('Provider Web App -
Mobile Responsiveness') block—specifically the tests named 'should render
correctly on mobile viewport' and 'should have touch-friendly elements on
mobile' that call page.goto('/provider/dashboard') (and similarly another test
visiting '/admin/dashboard') are in the Customer app e2e suite and will 404;
either move these test cases into the correct app suites
(MeAjudaAi.Web.Provider/e2e and MeAjudaAi.Web.Admin/e2e) or change their
navigation to absolute URLs that point to the Provider/Admin baseURLs, updating
the page.goto calls accordingly so they use the proper host/port for those apps
while keeping the rest of the test logic (viewport via mobileViewport, locator
checks, and button boundingBox assertions) intact.
- Around line 119-137: The test "should meet FID threshold" never generates a
first-input entry because it doesn't perform a user interaction; update the test
to register the PerformanceObserver (the code that creates new
PerformanceObserver and resolves metrics) before simulating a real user gesture,
then programmatically trigger a real user interaction (e.g., await
page.click('body') or a specific interactive element) so the PerformanceObserver
can capture a 'first-input' entry (fidEntry). Ensure you wait for the observer
to resolve (or extend the timeout) and then assert metrics.fid < 100 as before;
reference the test name, the PerformanceObserver/ fidEntry logic and the metrics
variable when making the change.
- Around line 102-116: The LCP measurement can race/leave the
PerformanceObserver attached; inside the page.evaluate Promise (where metrics is
produced) ensure you only resolve once and always clean up: create a boolean
flag (e.g., resolved) so both the PerformanceObserver callback and the
setTimeout check/set the flag before calling resolve, call observer.disconnect()
inside the observer callback after capturing the LCP, and clear the timeout
(clearTimeout) when resolving from the observer; also ensure the timeout path
disconnects the observer before resolving—apply these changes around the
PerformanceObserver, setTimeout and resolve logic so the observer is always
disconnected and the Promise resolves exactly once.
---
Duplicate comments:
In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts`:
- Around line 9-11: The tests expect data-testid attributes that don't exist:
update the providers page component (providers/page.tsx) and the related
provider row/detail elements to include data-testid="providers-table",
data-testid="provider-row", data-testid="provider-status",
data-testid="documents-list", data-testid="provider-detail",
data-testid="approve-button" and data-testid="view-details" on the corresponding
<table>, row, status cell, documents list, detail panel and action buttons (or
if you prefer not to add attributes, change the tests to use existing selectors
such as table, tbody tr, aria-label values or role-based queries); ensure the
exact testid strings match those used in the spec so the locators in the test
(providers.spec.ts) can find the elements.
---
Nitpick comments:
In `@src/Web/libs/e2e-support/base.ts`:
- Around line 43-46: A função logout tenta clicar no botão "Sair" sem verificar
se ele existe, causando timeout se o usuário já estiver deslogado; modifique
logout (exported function logout(page: Page)) para primeiro localizar o botão
via page.locator or page.getByRole (name: /sair/i) e checar
presença/visibilidade (ex.: count()>0 ou isVisible()) antes de clicar, só
executar o click e o await page.waitForURL(...) quando o botão existir; se não
existir, retorne imediatamente para evitar falha do teste.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts`:
- Around line 30-31: The test uses a brittle fixed sleep via
page.waitForTimeout(500); replace this magic wait with an explicit wait that
reflects the real condition: e.g., wait for the filter result element or network
response instead. Locate the usage of page.waitForTimeout in providers.spec.ts
and change it to an appropriate explicit wait such as locator.waitFor({ state:
'visible' }) on the element that indicates the filter has applied (or
page.waitForResponse matching the filter request) so the test only proceeds once
the UI or network state is ready.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.ts`:
- Line 1: The import statement in onboarding.spec.ts includes unused symbols
loginAsCustomer and logout; remove these unused imports from the import
declaration so it only imports the actually used symbols (test, expect) to clean
up the file and avoid linter warnings.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 182-183: The current assertion uses lazyLoadedImages and will fail
if there are no lazy images above the fold; update the check to only assert lazy
loading for images below the fold by computing viewport height (e.g.,
window.innerHeight or document.documentElement.clientHeight), filter
imagesWithSrc by element.getBoundingClientRect().top > viewportHeight to get
imagesBelowFold, then either assert that every image in imagesBelowFold has
loading === 'lazy' or make the assertion conditional (only run expect when
imagesBelowFold.length > 0). Reference the existing variables lazyLoadedImages
and imagesWithSrc and replace the current expect line with the
conditional/below-the-fold-based assertion.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4cc62ff9-02fe-4f6f-9cfa-3fa0c6f2276b
⛔ Files ignored due to path filters (3)
src/Web/MeAjudaAi.Web.Provider/e2e/auth.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**src/Web/MeAjudaAi.Web.Provider/e2e/onboarding.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**src/Web/MeAjudaAi.Web.Provider/e2e/profile-mgmt.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**
📒 Files selected for processing (18)
.github/workflows/master-ci-cd.yml.gitignoredocs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdsrc/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/configs.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/search.spec.tssrc/Web/libs/e2e-support/.eslintrc.jsonsrc/Web/libs/e2e-support/base.tssrc/Web/libs/e2e-support/project.jsonsrc/Web/libs/e2e-support/tsconfig.jsonsrc/Web/libs/e2e-support/tsconfig.lib.jsonsrc/Web/playwright.config.ts
✅ Files skipped from review due to trivial changes (8)
- .gitignore
- src/Web/libs/e2e-support/.eslintrc.json
- src/Web/libs/e2e-support/tsconfig.json
- src/Web/MeAjudaAi.Web.Customer/e2e/auth.spec.ts
- src/Web/libs/e2e-support/project.json
- src/Web/MeAjudaAi.Web.Admin/e2e/auth.spec.ts
- src/Web/MeAjudaAi.Web.Customer/e2e/search.spec.ts
- .github/workflows/master-ci-cd.yml
🚧 Files skipped from review as they are similar to previous changes (2)
- src/Web/libs/e2e-support/tsconfig.lib.json
- src/Web/playwright.config.ts
…tion, and initial e2e test suite for web applications.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (6)
docs/roadmap-current.md (2)
617-621:⚠️ Potential issue | 🟠 MajorMantenha um único significado para “Sprint 8E” em todo o roadmap.
Este cabeçalho define Sprint 8E como E2E React Apps, mas o documento ainda menciona “Sprint 8E (Mobile)” em outra seção. Unifique para evitar conflito de escopo e leitura de planejamento.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap-current.md` around lines 617 - 621, O documento usa “Sprint 8E” com significados divergentes; unifique o nome em todo o roadmap para evitar ambiguidade: escolha entre “Sprint 8E - E2E React Apps (Playwright)” (como no cabeçalho e branch `feature/sprint-8e-e2e-react-apps`) ou “Sprint 8E (Mobile)”, e atualize todas as ocorrências do outro termo para o escolhido; verifique e altere títulos, subtítulos e descrições que mencionem “Sprint 8E (Mobile)” para corresponder ao termo único, mantendo o período (23 Mar - 4 Abr 2026) e a branch referenciada consistentes.
35-39:⚠️ Potential issue | 🟠 MajorUnifique a narrativa da stack do Admin Portal no bloco inteiro.
O trecho de Line 35-39 marca Admin como React migrado, mas o mesmo bloco ainda descreve Admin em Blazor/dual stack. Isso mantém ambiguidade de estado atual.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap-current.md` around lines 35 - 39, O bloco "Admin Portal (React - migrado Sprint 8D)" está inconsistente porque mistura indicação de migração para React com descrições de Blazor/dual stack; atualize o parágrafo inteiro para uma única narrativa afirmando que o Admin já foi migrado para React (ou, se ainda não foi, marque claramente como "em migração") e remova qualquer menção a Blazor/dual stack; garanta que as tecnologias listadas (React 19, TypeScript 5.7+, Tailwind CSS v4, Zustand, React Hook Form + Zod) correspondam ao estado escolhido e ajuste a frase de cabeçalho "Admin Portal (React - migrado Sprint 8D)" para refletir o estado final de forma inequívoca.docs/admin-portal/overview.md (1)
102-113:⚠️ Potential issue | 🟠 MajorAtualize os caminhos de E2E para a nova estrutura de testes.
A documentação ainda aponta para
src/Web/MeAjudaAi.Web.Admin/e2e/esrc/Web/libs/e2e-support/base.ts, mas o escopo deste PR descreve a estrutura emtests/MeAjudaAi.Web.*.Tests/com shared fixtures. Isso pode levar a setup e execução incorretos.📌 Ajuste sugerido
-Localização: `src/Web/MeAjudaAi.Web.Admin/e2e/` +Localização: `tests/MeAjudaAi.Web.Admin.Tests/e2e/` -**Fixtures compartilhadas:** `src/Web/libs/e2e-support/base.ts` +**Fixtures compartilhadas:** `tests/MeAjudaAi.Web.Shared.Tests/base.ts`🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 102 - 113, Atualize a seção E2E para refletir a nova estrutura de testes: substitua referências a src/Web/MeAjudaAi.Web.Admin/e2e/ e src/Web/libs/e2e-support/base.ts pela pasta de testes atual tests/MeAjudaAi.Web.*.Tests/ e pelo local dos fixtures compartilhados (onde o shared fixture loginAsAdmin agora vive), atualizando a árvore de exemplo, os caminhos nos trechos de documentação e o nome/posição do fixture `loginAsAdmin` para apontar para a nova pasta de shared fixtures usada pelo PR.docs/architecture.md (2)
3113-3169:⚠️ Potential issue | 🟠 MajorPadronize a estrutura E2E desta página com a estrutura nova da PR.
O documento ainda descreve testes co-localizados (
src/Web/.../e2e), enquanto o PR aponta reorganização paratests/MeAjudaAi.Web.*.Tests/+ shared tests. Isso pode quebrar onboarding e execução dos exemplos.📌 Ajuste sugerido (resumo)
-src/Web/MeAjudaAi.Web.Admin/.../e2e/ -src/Web/MeAjudaAi.Web.Customer/.../e2e/ -src/Web/MeAjudaAi.Web.Provider/.../e2e/ +tests/MeAjudaAi.Web.Admin.Tests/e2e/ +tests/MeAjudaAi.Web.Customer.Tests/e2e/ +tests/MeAjudaAi.Web.Provider.Tests/e2e/ +tests/MeAjudaAi.Web.Shared.Tests/base.ts🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 3113 - 3169, Update the E2E section in docs/architecture.md to match the new PR layout: replace all references to co-located e2e folders (e.g., src/Web/MeAjudaAi.Web.Admin/e2e, src/Web/MeAjudaAi.Web.Customer/e2e, src/Web/MeAjudaAi.Web.Provider/e2e) with the new test project paths (tests/MeAjudaAi.Web.Admin.Tests, tests/MeAjudaAi.Web.Customer.Tests, tests/MeAjudaAi.Web.Provider.Tests) and document the shared tests/libs location (e.g., tests/shared or libs/e2e-support) plus update the Playwright config description to reflect the single test repo layout and any changed testDir/baseURL/grep expectations so examples and onboarding match the PR.
2781-2827:⚠️ Potential issue | 🟠 MajorA seção nova de frontend React conflita com exemplos Blazor ainda presentes no mesmo capítulo.
Após a migração descrita aqui, o leitor encontra adiante fluxo de autenticação em Blazor (
Program.csOIDC +.razor). Recomendo separar explicitamente “arquitetura atual (React)” de “histórico legado (Blazor)” para evitar implementação equivocada.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 2781 - 2827, Split the chapter into explicit "Current architecture (React + Next.js + Tailwind CSS)" and "Legacy (Blazor)" subsections: keep the existing React content (the "React + Next.js + Tailwind CSS" heading, mermaid diagram, and the Stack Tecnológica table) under the Current architecture subsection, and move any Blazor-specific examples (references to Program.cs OIDC and .razor files) into a separate "Legacy (Blazor)" subsection with a short note that these are historical/legacy examples; update headings and add a one-line disclaimer in each subsection clarifying which examples are active vs. legacy so readers cannot confuse Program.cs/.razor Blazor code with the current React implementation.src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts (1)
83-116:⚠️ Potential issue | 🟠 MajorTeste de FID pode passar sem medir FID (falso positivo)
Em Line [109],
document.body.click()é clique sintético no contexto da página e pode não gerar entry defirst-input. Em Line [113], a condiçãoif (metrics.fid)pula a validação quandofidénull, então o teste passa mesmo sem métrica válida.💡 Ajuste sugerido
test('should meet FID threshold', async ({ page }) => { await page.goto('/'); - - const metrics = await page.evaluate(async () => { - return new Promise((resolve) => { + + await page.evaluate(() => { + (window as any).__fidPromise = new Promise<{ fid: number | null }>((resolve) => { let resolved = false; const observer = new PerformanceObserver((list) => { if (resolved) return; const entries = list.getEntries(); const fidEntry = entries.find((entry) => entry.entryType === 'first-input'); if (fidEntry) { resolved = true; observer.disconnect(); resolve({ fid: (fidEntry as any).processingStart - fidEntry.startTime }); } }); observer.observe({ type: 'first-input', buffered: true }); - - setTimeout(() => { + + setTimeout(() => { if (!resolved) { resolved = true; observer.disconnect(); resolve({ fid: null }); } }, 5000); - - document.body.click(); }); }); - - if (metrics.fid) { - expect(metrics.fid).toBeLessThan(100); - } + + await page.mouse.click(10, 10); + const metrics = await page.evaluate(() => (window as any).__fidPromise); + + expect(metrics.fid).not.toBeNull(); + expect(metrics.fid).toBeLessThan(100); });A entrada `first-input` do PerformanceObserver é gerada por `document.body.click()` programático, ou apenas por interação real do usuário (eventos trusted)? Traga referências de MDN/W3C.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts` around lines 83 - 116, The test can falsely pass because document.body.click() inside page.evaluate may not produce a trusted first-input entry and the assertion skips when metrics.fid is null; move the user interaction out of the page.evaluate and perform a real user gesture with Playwright (e.g., use page.mouse.click(x,y) or await page.click('body') before collecting metrics) so the PerformanceObserver in the evaluate callback can capture a genuine first-input entry, and change the assertion to explicitly require a non-null FID (e.g., expect(metrics.fid).not.toBeNull()) before asserting expect(metrics.fid).toBeLessThan(100); update references to the test name, the metrics variable, and the PerformanceObserver logic accordingly.
🧹 Nitpick comments (2)
src/Web/MeAjudaAi.Web.Admin/e2e/performance.spec.ts (1)
5-8: Inconsistência entre nome do arquivo e conteúdo do teste.O arquivo se chama
performance.spec.ts, mas a suite de testes é "Admin Portal - Mobile Responsiveness". Testes de responsividade mobile não são exatamente testes de performance. Considere renomear o arquivo paramobile-responsiveness.spec.tsouresponsive.spec.tspara melhor organização e clareza ao filtrar/executar testes.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/performance.spec.ts` around lines 5 - 8, The test file name (performance.spec.ts) doesn't match the test suite title ("Admin Portal - Mobile Responsiveness"); either rename the file to something like mobile-responsiveness.spec.ts or responsive.spec.ts, or change the test.describe title to reflect performance tests (e.g., "Admin Portal - Performance"); update any test runner configs or imports that reference the file name if you rename it, and keep the test.describe string and filename consistent (reference: the test.describe block and the file name performance.spec.ts).docs/admin-portal/overview.md (1)
159-167: Redirecione emuseEffectao invés de durante render.No exemplo da linha 165,
router.push('/login')é chamado durante a renderização, o que pode causar comportamentos inesperados e re-render loops. Mova o redirecionamento para umuseEffectque observe mudanças no estado da sessão.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/admin-portal/overview.md` around lines 159 - 167, O componente AdminProtected está chamando router.push('/login') durante a render (inside AdminProtected after useSession), o que pode causar re-renders indesejados; move the redirect into a useEffect that watches status and session: keep the existing loading branch returning <Spinner />, and instead of calling router.push during render, add a useEffect that runs when status or session change and calls router.push('/login') if status !== 'loading' and !session; ensure the render returns null (or a fallback) while redirecting to avoid side effects during render.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Web/MeAjudaAi.Web.Admin/e2e/performance.spec.ts`:
- Around line 17-23: The test "should collapse sidebar on mobile" fails because
the Sidebar component's <aside> element lacks the data-testid="sidebar"
attribute; update the Sidebar component (the <aside> element in the Sidebar
component) to include data-testid="sidebar" so the locator in the e2e test can
find it, then run the e2e test to confirm the locator
(page.locator('[data-testid="sidebar"]')) now succeeds.
- Around line 10-15: O componente de layout (sidebar.tsx) está sem os atributos
usados pelos testes; abra o componente Sidebar e adicione
data-testid="mobile-menu-toggle" no botão hamburger (o elemento de toggle do
menu), data-testid="sidebar" no elemento <aside> principal do sidebar e
data-testid="mobile-menu" no container do menu móvel (o elemento que aparece em
mobile); assim os seletores usados em performance.spec.ts poderão localizar
corretamente os elementos.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Line 37: O teste de performance usa await page.goto('/busca') mas o aplicativo
realmente navega para '/buscar' (ver componente Header em header.tsx); atualize
a chamada page.goto no arquivo performance.spec.ts para usar '/buscar' para
evitar 404 e garantir que asserções de layout mobile atinjam a rota correta.
---
Duplicate comments:
In `@docs/admin-portal/overview.md`:
- Around line 102-113: Atualize a seção E2E para refletir a nova estrutura de
testes: substitua referências a src/Web/MeAjudaAi.Web.Admin/e2e/ e
src/Web/libs/e2e-support/base.ts pela pasta de testes atual
tests/MeAjudaAi.Web.*.Tests/ e pelo local dos fixtures compartilhados (onde o
shared fixture loginAsAdmin agora vive), atualizando a árvore de exemplo, os
caminhos nos trechos de documentação e o nome/posição do fixture `loginAsAdmin`
para apontar para a nova pasta de shared fixtures usada pelo PR.
In `@docs/architecture.md`:
- Around line 3113-3169: Update the E2E section in docs/architecture.md to match
the new PR layout: replace all references to co-located e2e folders (e.g.,
src/Web/MeAjudaAi.Web.Admin/e2e, src/Web/MeAjudaAi.Web.Customer/e2e,
src/Web/MeAjudaAi.Web.Provider/e2e) with the new test project paths
(tests/MeAjudaAi.Web.Admin.Tests, tests/MeAjudaAi.Web.Customer.Tests,
tests/MeAjudaAi.Web.Provider.Tests) and document the shared tests/libs location
(e.g., tests/shared or libs/e2e-support) plus update the Playwright config
description to reflect the single test repo layout and any changed
testDir/baseURL/grep expectations so examples and onboarding match the PR.
- Around line 2781-2827: Split the chapter into explicit "Current architecture
(React + Next.js + Tailwind CSS)" and "Legacy (Blazor)" subsections: keep the
existing React content (the "React + Next.js + Tailwind CSS" heading, mermaid
diagram, and the Stack Tecnológica table) under the Current architecture
subsection, and move any Blazor-specific examples (references to Program.cs OIDC
and .razor files) into a separate "Legacy (Blazor)" subsection with a short note
that these are historical/legacy examples; update headings and add a one-line
disclaimer in each subsection clarifying which examples are active vs. legacy so
readers cannot confuse Program.cs/.razor Blazor code with the current React
implementation.
In `@docs/roadmap-current.md`:
- Around line 617-621: O documento usa “Sprint 8E” com significados divergentes;
unifique o nome em todo o roadmap para evitar ambiguidade: escolha entre “Sprint
8E - E2E React Apps (Playwright)” (como no cabeçalho e branch
`feature/sprint-8e-e2e-react-apps`) ou “Sprint 8E (Mobile)”, e atualize todas as
ocorrências do outro termo para o escolhido; verifique e altere títulos,
subtítulos e descrições que mencionem “Sprint 8E (Mobile)” para corresponder ao
termo único, mantendo o período (23 Mar - 4 Abr 2026) e a branch referenciada
consistentes.
- Around line 35-39: O bloco "Admin Portal (React - migrado Sprint 8D)" está
inconsistente porque mistura indicação de migração para React com descrições de
Blazor/dual stack; atualize o parágrafo inteiro para uma única narrativa
afirmando que o Admin já foi migrado para React (ou, se ainda não foi, marque
claramente como "em migração") e remova qualquer menção a Blazor/dual stack;
garanta que as tecnologias listadas (React 19, TypeScript 5.7+, Tailwind CSS v4,
Zustand, React Hook Form + Zod) correspondam ao estado escolhido e ajuste a
frase de cabeçalho "Admin Portal (React - migrado Sprint 8D)" para refletir o
estado final de forma inequívoca.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 83-116: The test can falsely pass because document.body.click()
inside page.evaluate may not produce a trusted first-input entry and the
assertion skips when metrics.fid is null; move the user interaction out of the
page.evaluate and perform a real user gesture with Playwright (e.g., use
page.mouse.click(x,y) or await page.click('body') before collecting metrics) so
the PerformanceObserver in the evaluate callback can capture a genuine
first-input entry, and change the assertion to explicitly require a non-null FID
(e.g., expect(metrics.fid).not.toBeNull()) before asserting
expect(metrics.fid).toBeLessThan(100); update references to the test name, the
metrics variable, and the PerformanceObserver logic accordingly.
---
Nitpick comments:
In `@docs/admin-portal/overview.md`:
- Around line 159-167: O componente AdminProtected está chamando
router.push('/login') durante a render (inside AdminProtected after useSession),
o que pode causar re-renders indesejados; move the redirect into a useEffect
that watches status and session: keep the existing loading branch returning
<Spinner />, and instead of calling router.push during render, add a useEffect
that runs when status or session change and calls router.push('/login') if
status !== 'loading' and !session; ensure the render returns null (or a
fallback) while redirecting to avoid side effects during render.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/performance.spec.ts`:
- Around line 5-8: The test file name (performance.spec.ts) doesn't match the
test suite title ("Admin Portal - Mobile Responsiveness"); either rename the
file to something like mobile-responsiveness.spec.ts or responsive.spec.ts, or
change the test.describe title to reflect performance tests (e.g., "Admin Portal
- Performance"); update any test runner configs or imports that reference the
file name if you rename it, and keep the test.describe string and filename
consistent (reference: the test.describe block and the file name
performance.spec.ts).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6aee93f3-a484-4846-bb04-15ba74e090bd
⛔ Files ignored due to path filters (1)
src/Web/MeAjudaAi.Web.Provider/e2e/performance.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**
📒 Files selected for processing (9)
docs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdsrc/Web/MeAjudaAi.Web.Admin/e2e/configs.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/performance.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.tssrc/Web/libs/e2e-support/base.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- src/Web/MeAjudaAi.Web.Customer/e2e/onboarding.spec.ts
- src/Web/MeAjudaAi.Web.Admin/e2e/providers.spec.ts
- src/Web/MeAjudaAi.Web.Admin/e2e/configs.spec.ts
- src/Web/libs/e2e-support/base.ts
…or customer, admin, and provider applications, and create new documentation files for architecture, admin portal, and roadmap.
…fo, theme toggle, and logout functionality.
There was a problem hiding this comment.
Actionable comments posted: 16
🧹 Nitpick comments (3)
src/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts (1)
65-65: EvitewaitForTimeoutfixo; isso aumenta flakiness e tempo da suíte.Prefira esperar por estado/elemento específico (
toBeVisible,toHaveURL,waitForLoadState) em vez de sleep fixo.Also applies to: 79-79, 95-95, 109-109, 126-126, 218-218
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts` at line 65, There are multiple uses of fixed sleeps (page.waitForTimeout) in profile.spec.ts which make tests flaky and slow; replace each await page.waitForTimeout(...) with deterministic waits tied to the expected state: after navigations use page.waitForLoadState('networkidle') or expect(page).toHaveURL(expectedPath), and for DOM changes wait on specific locators via await page.locator('<selector>').waitFor({state: 'visible' | 'attached'}) or await expect(page.locator('<selector>')).toBeVisible(); update all occurrences (the calls to page.waitForTimeout in this spec) to use the appropriate page.waitForLoadState/expect(...).toHaveURL or locator.waitFor/expect(locator).toBeVisible with the correct selectors for the element each test is relying on.docs/architecture.md (1)
3236-3236: Adicionar especificador de linguagem ao bloco de código.O bloco de código que mostra a estrutura de arquivos está sem especificador de linguagem, gerando warning de lint (MD040).
💡 Correção sugerida
-``` +```text src/Web/ ├── MeAjudaAi.Web.Admin/ # Admin Portal Next.js App ...🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` at line 3236, The fenced code block that shows the file structure is missing a language specifier and triggers MD040; update the code block surrounding the file tree (the triple-backtick block in the architecture document) to include a language specifier such as "text" (i.e., change ``` to ```text) so the linter recognizes it; ensure you do this for the specific code block that starts with "src/Web/" so the warning is resolved.src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts (1)
83-116: Se a intenção é cobrir Core Web Vitals atuais, este caso deveria medir INP.FID deixou de ser Core Web Vital estável e foi substituída por INP. Manter esse gate aqui passa uma cobertura desatualizada de responsividade. (web.dev)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts` around lines 83 - 116, The test currently measures FID (test "should meet FID threshold") which is deprecated; update it to measure INP instead by renaming the test (e.g., "should meet INP threshold") and replacing the PerformanceObserver logic inside the page.evaluate: observe type 'event' with buffered: true, filter entries where entry.entryType === 'event', compute INP as the maximum candidate across those entries using the web.dev formula (for each entry use processingStart + duration - startTime when processingStart exists, otherwise use duration), resolve with { inp: calculatedValue } (and timeout to return inp: null), then assert metrics.inp is not null and meets the INP threshold (adjust expectation from metrics.fid to metrics.inp and update the numeric threshold accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/admin-portal/overview.md`:
- Around line 102-119: Update the documentation to reflect the actual locations:
change the E2E tests path from tests/MeAjudaAi.Web.Admin.Tests/e2e/ to
src/Web/MeAjudaAi.Web.Admin/e2e/ (the actual test files include
providers.spec.ts, auth.spec.ts, configs.spec.ts, dashboard.spec.ts,
mobile-responsiveness.spec.ts) and update the shared fixtures path from
tests/MeAjudaAi.Web.Shared.Tests/base.ts to src/Web/libs/e2e-support/base.ts
(which exports loginAsAdmin, loginAsProvider, loginAsCustomer and logout);
ensure the overview.md examples and the listed fixture exports reference these
real file paths and the existing exported helper names.
In `@docs/architecture.md`:
- Around line 3177-3207: The docs entry incorrectly points to the old
shared-fixtures location; update the architecture documentation to reference the
actual shared E2E support module that exports the helpers loginAsAdmin,
loginAsProvider, loginAsCustomer and logout and remove the obsolete
tests/MeAjudaAi.Web.Shared.Tests/base.ts reference so consumers know to import
those helpers from the real shared support module; ensure the tests listing
reflects the new shared-support placement and the example import paths in the
docs use the module that contains those exported functions.
In `@docs/roadmap-current.md`:
- Line 630: Atualize a referência aos fixtures E2E na documentação corrigindo o
caminho mencionado; substitua a entrada que aponta para
tests/MeAjudaAi.Web.Shared.Tests/base.ts pela localização real onde estão
exportados loginAsAdmin, loginAsProvider, loginAsCustomer e logout
(src/Web/libs/e2e-support/base.ts) para que o documento aponte para o arquivo
correto e reflita os símbolos exportados.
In `@src/Web/MeAjudaAi.Web.Admin/components/layout/sidebar.tsx`:
- Around line 47-58: No JSX attributes should use `class`; change the invalid
`class` props to `className` on the mobile toggle button and the backdrop div in
the sidebar component (the elements using onClick={() => setIsOpen(true)} /
data-testid="mobile-menu-toggle" and the conditional backdrop rendered when
isOpen is true). Ensure both occurrences are updated (the button with <Menu />
and the div with fixed inset-0 bg-black/50) and scan the rest of sidebar.tsx for
any other `class` → `className` fixes so TypeScript/React typings build
correctly.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.ts`:
- Around line 165-170: O teste "should display loading state while fetching
data" está sujeito a race condition porque verifica o spinner logo após
page.goto() sem interceptar a chamada de dados; use page.route(...) para mockar
a API (ou adicionar um delay) ou aguarde explicitamente a requisição com
page.waitForResponse(...) antes de executar expect(on) no locator
'[data-testid="dashboard-loading"]' para garantir que o estado de loading seja
visível durante a asserção.
- Around line 145-156: The test 'should refresh data on button click' is flaky
because it uses a fixed wait (waitForTimeout(1000)) and only asserts that
kpiValueAfter is defined; replace the fixed sleep with a reactive wait that
waits for the KPI value to change and assert the values differ. Specifically, in
the test body locate the refresh button (refreshButton) and capture
kpiValueBefore, click refreshButton, then use a wait-for condition (e.g.,
waitFor or locator.waitFor with a predicate) to wait until the locator for
'[data-testid="kpi-total-providers"] [data-testid="kpi-value"]' textContent
changes from kpiValueBefore, then read kpiValueAfter and assert kpiValueAfter
!== kpiValueBefore to confirm the refresh actually updated data.
- Around line 172-181: O teste "should handle API error gracefully" atualmente
só lê o DOM e pode passar sem erro real; altere-o para injetar uma falha via
page.route() antes de navegar (ou antes da ação que chama a API) para forçar a
resposta de erro HTTP, então remova a condição if(hasError) e sempre assert que
errorMessage (locator '[data-testid="dashboard-error"]') contém o texto esperado
e que retryButton (locator '[data-testid="retry-button"]') está visível;
mantenha os nomes das variáveis errorMessage e retryButton e garanta que a rota
mock retorne um status de erro e corpo apropriado para disparar o tratamento de
erro da UI.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/mobile-responsiveness.spec.ts`:
- Around line 10-15: The test "should render correctly on mobile viewport" fails
because the sidebar in sidebar.tsx is hidden by default (aside starts with
translate-x-full when isOpen=false); update the test to emulate user interaction
by clicking the mobile hamburger/toggle before asserting the menu is visible:
after setting mobileViewport and navigating to '/admin/dashboard' add a click on
the hamburger toggle (the button that toggles isOpen — e.g., the mobile
hamburger data-testid used in the UI) and then assert that
'[data-testid="mobile-menu"]' is visible.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 171-182: O teste "should not have excessive requests" atualmente
só conta requests com 'localhost'/'127.0.0.1' dentro do handler
page.on('request'), o que ignora tráfego de terceiros; corrija isto alterando o
filtro no handler para contabilizar todos os requests relevantes (remova a
checagem de origem ou adicione uma whitelist/blacklist explícita) e ajustar a
expectativa expect(requests.length).toBeLessThan(50) de acordo, ou
alternativamente renomeie o caso de teste para algo como "should not have
excessive same-origin requests" para deixar claro que só mede same-origin,
mantendo a lógica atual em page.on('request') e a asserção.
- Around line 78-80: The current LCP check can pass when metrics.lcp is null
because the threshold assertion is skipped; update the test around metrics.lcp
to first assert it is defined/non-null (e.g., expect(metrics.lcp).toBeDefined()
or toBeGreaterThan(0)) and then assert the numeric threshold
(expect(metrics.lcp).toBeLessThan(2500)), ensuring both checks run so a missing
metric fails the test; look for the metrics.lcp check in the performance.spec.ts
test and add the presence assertion before the toBeLessThan assertion.
- Around line 123-131: The CLS calculation currently sums all layout-shift
entries (within page.evaluate using performance.getEntriesByType('layout-shift')
and entries.forEach) which is the old approach; change it to the official
"session windows" algorithm: filter out entries with entry.hadRecentInput, then
iterate the remaining entries in time order grouping them into windows where
consecutive shifts are < 1s apart and each window duration ≤ 5s, compute the sum
of entry.value per window, and return the maximum window sum (e.g., replace the
single accumulator cls with a maxCls computed from per-window sums and return {
cls: maxCls }). Ensure this logic lives inside the same page.evaluate block so
metrics captures the session-windowed CLS.
- Around line 137-143: O tempo atual mede na verdade até o evento load porque
page.goto() aguarda load por padrão; para medir apenas domcontentloaded atualize
o teste dentro do bloco "should load page within acceptable time" para iniciar
startTime antes da navegação e chamar page.goto('/', { waitUntil:
'domcontentloaded' }) (removendo o page.waitForLoadState('domcontentloaded')
redundante), então calcular loadTime = Date.now() - startTime e manter a
asserção expect(loadTime).toBeLessThan(3000); referencie as variáveis startTime,
loadTime e os métodos page.goto / page.waitForLoadState ao aplicar a mudança.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts`:
- Around line 235-240: The test risks an out-of-bounds access by calling
ratingStars.nth(4) without ensuring there are at least five stars; update the
check around the ratingStars locator (variables ratingStars and starsCount) to
assert starsCount >= 5 before clicking the fifth star, or compute the target
index safely (e.g., use Math.min(4, starsCount - 1) or click the last star) and
apply the same guard/fix to the other occurrence at lines 262-265; ensure the
expectation and subsequent click use the safe index instead of unguarded nth(4).
- Around line 49-59: The test "should show login prompt for guest users" uses a
conditional that masks failures; remove the if-check and assert
deterministically that the login prompt exists and is visible by replacing the
conditional branch with explicit expectations on the locator returned by
page.locator('[data-testid="login-prompt"]') (e.g., assert count is > 0 or use
toBeVisible()/toHaveCount) so the test fails when the element is absent; apply
the same change pattern to the other tests noted (the ones using the same
count-if pattern).
- Line 276: Remove the silent catch so test failures propagate: in
profile.spec.ts, locate the assertion awaiting page.locator('text=Obrigado pela
avaliação') and delete the trailing .catch(() => {}); keep the await
expect(...).toBeVisible({ timeout: 5000 }) as-is (or replace with a deliberate
try/catch that rethrows or logs then throws) so a missing confirmation fails the
test instead of being suppressed.
- Line 3: The test suite's describe title "Customer Web App - Provider Profile
View" (test.describe in profile.spec.ts) lacks the required e2e marker so it may
be filtered out by the global grep (/e2e/) in playwright.config.ts; update the
test.describe titles used across e2e specs—starting with test.describe in
src/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts—to include the prefix "@e2e"
(e.g., "@e2e Customer Web App - Provider Profile View") so the CI collects these
suites; ensure all other describe blocks in the e2e folder follow the same
naming convention.
---
Nitpick comments:
In `@docs/architecture.md`:
- Line 3236: The fenced code block that shows the file structure is missing a
language specifier and triggers MD040; update the code block surrounding the
file tree (the triple-backtick block in the architecture document) to include a
language specifier such as "text" (i.e., change ``` to ```text) so the linter
recognizes it; ensure you do this for the specific code block that starts with
"src/Web/" so the warning is resolved.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 83-116: The test currently measures FID (test "should meet FID
threshold") which is deprecated; update it to measure INP instead by renaming
the test (e.g., "should meet INP threshold") and replacing the
PerformanceObserver logic inside the page.evaluate: observe type 'event' with
buffered: true, filter entries where entry.entryType === 'event', compute INP as
the maximum candidate across those entries using the web.dev formula (for each
entry use processingStart + duration - startTime when processingStart exists,
otherwise use duration), resolve with { inp: calculatedValue } (and timeout to
return inp: null), then assert metrics.inp is not null and meets the INP
threshold (adjust expectation from metrics.fid to metrics.inp and update the
numeric threshold accordingly).
In `@src/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts`:
- Line 65: There are multiple uses of fixed sleeps (page.waitForTimeout) in
profile.spec.ts which make tests flaky and slow; replace each await
page.waitForTimeout(...) with deterministic waits tied to the expected state:
after navigations use page.waitForLoadState('networkidle') or
expect(page).toHaveURL(expectedPath), and for DOM changes wait on specific
locators via await page.locator('<selector>').waitFor({state: 'visible' |
'attached'}) or await expect(page.locator('<selector>')).toBeVisible(); update
all occurrences (the calls to page.waitForTimeout in this spec) to use the
appropriate page.waitForLoadState/expect(...).toHaveURL or
locator.waitFor/expect(locator).toBeVisible with the correct selectors for the
element each test is relying on.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1a9617f4-c10e-4e3b-8148-a2a9eeb9681c
⛔ Files ignored due to path filters (1)
src/Web/MeAjudaAi.Web.Provider/e2e/dashboard.spec.tsis excluded by!**/MeAjudaAi.Web.Provider/**
📒 Files selected for processing (8)
docs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdsrc/Web/MeAjudaAi.Web.Admin/components/layout/sidebar.tsxsrc/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/mobile-responsiveness.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/Web/MeAjudaAi.Web.Admin/auth.ts (1)
13-22:requireEnvficou sem uso e duplica política de leitura de env.Hoje a função adiciona complexidade sem participar do fluxo real. Recomendo remover ou centralizar nela toda a leitura/validação para evitar drift futuro.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/auth.ts` around lines 13 - 22, The requireEnv function is unused and duplicates environment-reading policy; delete the requireEnv definition and any references, and centralize environment validation/reading into the existing configuration loader (instead of duplicating logic here). Specifically, remove the requireEnv function from auth.ts, move its intended behavior (required vs optional envs, validation, and logging policy) into your single config module (or a new getRequiredEnv/getConfig function), update code that previously/read envs to consume that centralized config API, and ensure the same production-only warning behavior is preserved there.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Web/MeAjudaAi.Web.Admin/auth.ts`:
- Around line 28-35: The current env-check allows placeholders in production
(only console.warn) — change the production branch so missing keycloakClientId,
keycloakClientSecret, or keycloakIssuer throws an error (e.g., throw new
Error("Missing Keycloak environment variables")) to fail fast; update the
conditional in the block that references
keycloakClientId/keycloakClientSecret/keycloakIssuer accordingly. Also
consolidate usage of the existing requireEnv helper: call requireEnv for those
three vars (or remove requireEnv if you prefer direct checks) so the helper is
not unused and environment validation is centralized.
---
Nitpick comments:
In `@src/Web/MeAjudaAi.Web.Admin/auth.ts`:
- Around line 13-22: The requireEnv function is unused and duplicates
environment-reading policy; delete the requireEnv definition and any references,
and centralize environment validation/reading into the existing configuration
loader (instead of duplicating logic here). Specifically, remove the requireEnv
function from auth.ts, move its intended behavior (required vs optional envs,
validation, and logging policy) into your single config module (or a new
getRequiredEnv/getConfig function), update code that previously/read envs to
consume that centralized config API, and ensure the same production-only warning
behavior is preserved there.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9d17603e-8f73-4cf3-a9dd-c607de53815a
📒 Files selected for processing (2)
src/Web/MeAjudaAi.Web.Admin/auth.tssrc/Web/MeAjudaAi.Web.Admin/components/layout/sidebar.tsx
✅ Files skipped from review due to trivial changes (1)
- src/Web/MeAjudaAi.Web.Admin/components/layout/sidebar.tsx
… portal overview, and current roadmap, alongside new E2E tests for admin dashboard, mobile responsiveness, customer performance, and profile.
… tests using Vitest and React Testing Library in the Nx monorepo.
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (8)
src/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.ts (2)
166-170:⚠️ Potential issue | 🟠 MajorEsse teste fica verde mesmo sem spinner.
O
.catch(() => {})engole a própria falha da assertion, então o caso passa quando o loading nunca aparece. Se a intenção é validar o estado de carregamento, force atraso/mocking da API e deixe a assertion falhar de verdade.💡 Ajuste sugerido
test('should display loading state while fetching data', async ({ page }) => { + await page.route('**/api/**', async (route) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + await route.continue(); + }); + await page.goto('/admin/dashboard'); const loadingSpinner = page.locator('[data-testid="dashboard-loading"]'); - await expect(loadingSpinner).toBeVisible({ timeout: 10000 }).catch(() => {}); + await expect(loadingSpinner).toBeVisible(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.ts` around lines 166 - 170, The test "should display loading state while fetching data" swallows assertion failures by using .catch(() => {}); remove the .catch and instead simulate a delayed API response (use page.route or network mocking for the dashboard data) so the loading spinner at locator '[data-testid="dashboard-loading"]' is actually shown, then assert with await expect(loadingSpinner).toBeVisible({ timeout: 10000 }) (no .catch) so the test fails correctly if the spinner never appears.
145-157:⚠️ Potential issue | 🟠 MajorO refresh não deveria depender de um KPI mudar.
kpi-total-providerspode continuar com o mesmo valor depois do refresh, entãonot.toBe(kpiValueBefore)gera falso negativo mesmo quando a atualização ocorreu. Um marcador como[data-testid="last-updated"]ou a própria request de refresh é um alvo melhor para provar a ação.💡 Ajuste sugerido
test('should refresh data on button click', async ({ page }) => { const refreshButton = page.locator('[data-testid="refresh-dashboard"]'); - const kpiValueLocator = page.locator('[data-testid="kpi-total-providers"] [data-testid="kpi-value"]'); - - const kpiValueBefore = await kpiValueLocator.textContent(); + const lastUpdated = page.locator('[data-testid="last-updated"]'); + const before = (await lastUpdated.textContent()) ?? ''; await refreshButton.click(); - - await kpiValueLocator.waitFor({ state: 'visible' }); - - const kpiValueAfter = await kpiValueLocator.textContent(); - expect(kpiValueAfter).not.toBe(kpiValueBefore); + + await expect.poll(async () => (await lastUpdated.textContent()) ?? '').not.toBe(before); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.ts` around lines 145 - 157, The test "should refresh data on button click" currently asserts that kpiValueLocator (data-testid="kpi-total-providers") changes, which can be flaky; update the test to verify a reliable indicator instead: use the refreshButton locator (data-testid="refresh-dashboard") to trigger the action and then assert either that the last-updated element (e.g. [data-testid="last-updated"]) textContent changed or that the network refresh request completed by intercepting the refresh API call; modify the test to capture the pre-refresh last-updated value (or wait for the mocked network route) and then after refresh click wait for the updated last-updated value (or for the routed response) and assert it changed or that the route was called, replacing the unreliable kpiValueLocator assertion.src/Web/MeAjudaAi.Web.Admin/auth.ts (1)
13-19:⚠️ Potential issue | 🟠 MajorFalhe cedo fora do CI quando faltar configuração do Keycloak.
O fallback final ainda injeta
placeholder/localhostfora do CI, então um deploy com segredo ausente sobe “saudável” e só quebra no primeiro login. Como os próprios workflows já passam valores dummy no build (.github/workflows/pr-validation.ymle.github/workflows/master-ci-cd.yml), esse branch deveria lançar erro fora do CI. De quebra,getRequiredEnvcontinua morto aqui.💡 Ajuste sugerido
+const isCI = process.env.CI === "true" || process.env.NEXT_PUBLIC_CI === "true"; +const isProd = process.env.NODE_ENV === "production"; + if (isFullyConfigured) { keycloakClientId = process.env.KEYCLOAK_ADMIN_CLIENT_ID || process.env.KEYCLOAK_CLIENT_ID!; keycloakClientSecret = process.env.KEYCLOAK_ADMIN_CLIENT_SECRET || process.env.KEYCLOAK_CLIENT_SECRET!; keycloakIssuer = process.env.KEYCLOAK_ISSUER!; -} else if (process.env.CI === "true" || process.env.NEXT_PUBLIC_CI === "true") { +} else if (isCI) { keycloakClientId = "placeholder"; keycloakClientSecret = "placeholder"; keycloakIssuer = "http://localhost:8080/realms/meajudaai"; console.warn("[auth] Warning: Missing Keycloak environment variables - using placeholder values for CI build."); +} else if (isProd) { + throw new Error("[auth] Missing required Keycloak environment variables."); } else { keycloakClientId = process.env.KEYCLOAK_ADMIN_CLIENT_ID || process.env.KEYCLOAK_CLIENT_ID || "placeholder"; keycloakClientSecret = process.env.KEYCLOAK_ADMIN_CLIENT_SECRET || process.env.KEYCLOAK_CLIENT_SECRET || "placeholder"; keycloakIssuer = process.env.KEYCLOAK_ISSUER || "http://localhost:8080/realms/meajudaai"; }Also applies to: 31-44
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Admin/auth.ts` around lines 13 - 19, The current auth bootstrap silently falls back to placeholder/localhost Keycloak values outside CI and never uses getRequiredEnv; change it to fail fast by using getRequiredEnv to read required Keycloak variables (e.g., KEYCLOAK_BASE_URL, KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID) instead of injecting defaults, and only allow dummy fallbacks when process.env.CI is explicitly truthy; update the Keycloak init code paths that currently set placeholder values to call getRequiredEnv (or conditionally allow dummy values when CI) so missing secrets throw an error at startup outside CI.docs/roadmap-current.md (2)
35-40:⚠️ Potential issue | 🟠 MajorA migração do Admin para React ficou atualizada só pela metade.
Este bloco agora diz que o Admin já está em React, mas o restante do roadmap ainda preserva narrativa/tabelas herdadas de Blazor. Publicado assim, o documento continua com dois estados “atuais” para o mesmo app.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap-current.md` around lines 35 - 40, O bloco "Admin Portal (React - migrado na Sprint 8D)" indica migração completa, mas o restante do documento ainda contém narrativas/tabelas referindo-se a Blazor; corrija a inconsistência atualizando o texto em docs/roadmap-current.md para refletir o estado real: ou marcar a migração como "parcial" e documentar os componentes ainda em Blazor, ou remover todas as referências a Blazor e ajustar as tabelas/narrativas subsequentes para React/TypeScript; busque e atualize as seções que mencionam "Blazor", "Admin Portal" e qualquer tabela de status para que todas usem o mesmo estado (migrado/parcial) e linguagem consistente.
624-631:⚠️ Potential issue | 🟡 MinorOs paths da Sprint 8E ainda apontam para projetos de teste inexistentes.
Os arquivos adicionados neste PR estão em
src/Web/MeAjudaAi.Web.Customer/e2e,src/Web/MeAjudaAi.Web.Provider/e2eesrc/Web/MeAjudaAi.Web.Admin/e2e, mas o escopo continua citandotests/MeAjudaAi.Web.*.Tests/e2e/. Isso conflita com a implementação real.💡 Ajuste sugerido
-3. **Customer Web App Tests**: Login, busca, perfil (`tests/MeAjudaAi.Web.Customer.Tests/e2e/`) -4. **Provider Web App Tests**: Onboarding, dashboard (`tests/MeAjudaAi.Web.Provider.Tests/e2e/`) -5. **Admin Portal Tests**: CRUD providers, documentos (`tests/MeAjudaAi.Web.Admin.Tests/e2e/`) +3. **Customer Web App Tests**: Login, busca, perfil (`src/Web/MeAjudaAi.Web.Customer/e2e/`) +4. **Provider Web App Tests**: Onboarding, dashboard (`src/Web/MeAjudaAi.Web.Provider/e2e/`) +5. **Admin Portal Tests**: CRUD providers, documentos (`src/Web/MeAjudaAi.Web.Admin/e2e/`)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/roadmap-current.md` around lines 624 - 631, The roadmap text references nonexistent test project paths ("tests/MeAjudaAi.Web.*.Tests/e2e/") while the PR added E2E suites under the actual projects (e.g., "src/Web/MeAjudaAi.Web.Customer/e2e", "src/Web/MeAjudaAi.Web.Provider/e2e", "src/Web/MeAjudaAi.Web.Admin/e2e"); update the Scope bullets (Playwright/Implement Test Specs/Customer/Provider/Admin entries and Shared Fixtures/CI Integration notes) to use the real project identifiers and correct e2e directories so the roadmap matches the implemented locations.src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts (2)
135-166:⚠️ Potential issue | 🟠 MajorA janela de CLS continua calculada de forma incorreta.
A regra oficial usa gap
< 1sentre shifts consecutivos e duração máxima de5spor janela. Aqui o reset acontece com base emwindowStartTime, então sequências como0ms → 800ms → 1600mssão quebradas cedo demais e o CLS fica subcontado.CLS session window gap 1 second 5 seconds official docs💡 Ajuste sugerido
let maxCls = 0; let currentWindowSum = 0; let windowStartTime = 0; + let lastEntryTime = 0; validEntries.forEach((entry) => { if (windowStartTime === 0) { windowStartTime = entry.startTime; + lastEntryTime = entry.startTime; currentWindowSum = entry.value; - } else if (entry.startTime - windowStartTime < 1000) { + } else if ( + entry.startTime - lastEntryTime < 1000 && + entry.startTime - windowStartTime < 5000 + ) { currentWindowSum += entry.value; + lastEntryTime = entry.startTime; } else { if (currentWindowSum > maxCls) { maxCls = currentWindowSum; } currentWindowSum = entry.value; windowStartTime = entry.startTime; + lastEntryTime = entry.startTime; } });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts` around lines 135 - 166, The CLS windowing logic under validEntries (variables maxCls, currentWindowSum, windowStartTime) is incorrect because it resets based on windowStartTime only; update it to follow the official CLS session rules: iterate sorted validEntries and start a new session when the gap between the current entry and the previous entry is >= 1000ms OR the current entry's startTime minus the session's windowStartTime is >= 5000ms; track lastEntryTime (previousStart) to check the 1s gap, update windowStartTime only when starting a new session, accumulate currentWindowSum otherwise, and update maxCls whenever you start a new session or at the end. Use the existing validEntries, maxCls, currentWindowSum, windowStartTime names to locate and replace the windowing logic.
83-125:⚠️ Potential issue | 🟠 MajorO observer de INP ainda começa tarde demais.
A interação acontece antes de o
PerformanceObserverser registrado. Se o clique for rápido, o teste continua sujeito a retornarnull, e semdurationThresholdvocê ainda filtra inputs curtos demais por padrão.PerformanceObserver event entries durationThreshold buffered INP official docs💡 Ajuste sugerido
test('should meet INP threshold', async ({ page }) => { await page.goto('/'); - - await page.waitForLoadState('domcontentloaded'); - - await page.click('body'); - - const metrics = await page.evaluate(() => { + + const metricsPromise = page.evaluate(() => { return new Promise((resolve) => { let resolved = false; const observer = new PerformanceObserver((list) => { @@ - observer.observe({ type: 'event', buffered: true }); + observer.observe({ type: 'event', buffered: true, durationThreshold: 16 }); @@ }); }); + + await page.click('body'); + const metrics = await metricsPromise;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts` around lines 83 - 125, The PerformanceObserver is registered too late because the test triggers page.click before the observer can capture the interaction; modify the test "should meet INP threshold" so the observer is created and observer.observe(...) is called before the user interaction, then trigger the click from within the page.evaluate block (or otherwise ensure page.click runs only after the observer resolves registration), set observer.observe to include durationThreshold: 0 and buffered: true (e.g. observer.observe({ type: 'event', buffered: true, durationThreshold: 0 })), and keep the fallback setTimeout logic; update references to the observer, metrics, and the setTimeout timeout if needed to ensure short interactions are captured and the promise resolves correctly.docs/architecture.md (1)
3176-3204:⚠️ Potential issue | 🟡 MinorOs caminhos e a organização de E2E ainda não batem com o repo real.
O tree usa
src/MeAjudaAi.Web.*e a guideline fala eme2e/admin, mas os arquivos deste PR estão co-localizados emsrc/Web/MeAjudaAi.Web.Admin/e2e,src/Web/MeAjudaAi.Web.Customer/e2e,src/Web/MeAjudaAi.Web.Provider/e2eesrc/Web/libs/e2e-support/base.ts. Assim como está, a documentação aponta para pastas inexistentes.💡 Ajuste sugerido
-```text -src/ -├── MeAjudaAi.Web.Admin/e2e/ # Admin Portal E2E tests +```text +src/Web/ +├── MeAjudaAi.Web.Admin/e2e/ # Admin Portal E2E tests │ ├── auth.spec.ts │ ├── providers.spec.ts │ ├── configs.spec.ts │ ├── dashboard.spec.ts │ └── mobile-responsiveness.spec.ts -├── MeAjudaAi.Web.Customer/e2e/ # Customer Web E2E tests +├── MeAjudaAi.Web.Customer/e2e/ # Customer Web E2E tests │ ├── auth.spec.ts │ ├── search.spec.ts │ ├── onboarding.spec.ts │ ├── profile.spec.ts │ └── performance.spec.ts -├── MeAjudaAi.Web.Provider/e2e/ # Provider Web E2E tests +├── MeAjudaAi.Web.Provider/e2e/ # Provider Web E2E tests │ ├── auth.spec.ts │ ├── onboarding.spec.ts │ ├── profile-mgmt.spec.ts │ ├── dashboard.spec.ts │ └── performance.spec.ts └── libs/e2e-support/ └── base.ts-- ✅ Separe testes por feature (e2e/admin, e2e/customer, etc.) +- ✅ Co-localize os testes por app (`MeAjudaAi.Web.Admin/e2e`, `MeAjudaAi.Web.Customer/e2e`, ...)Also applies to: 3229-3233
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/architecture.md` around lines 3176 - 3204, The documented E2E tree and Playwright config are pointing to nonexistent locations (e.g., "src/MeAjudaAi.Web.Admin/e2e" and testDir: './src') whereas the repo uses "src/Web/MeAjudaAi.Web.Admin/e2e", "src/Web/MeAjudaAi.Web.Customer/e2e", "src/Web/MeAjudaAi.Web.Provider/e2e" and "src/Web/libs/e2e-support/base.ts"; update the architecture.md snippet to show the actual directories (replace top-level "src/" with "src/Web/") and adjust the Playwright config example (change testDir from './src' to './src/Web' and update any baseDir/baseURL notes referencing the old paths) so the documentation matches the real repo layout and the exported helper reference (base.ts) points to src/Web/libs/e2e-support/base.ts.
🧹 Nitpick comments (1)
prompts/plano-implementacao-testes-react.md (1)
120-126: Remova a recomendação de@testing-library/react-hooksneste plano.
@testing-library/react-hooksé deprecated desde 2022. OrenderHookestá disponível nativamente em@testing-library/react(desde React 18) e é re-exportado viatest-utils.tsx, que o plano já utiliza (linhas 631, 641, 652). Instalar ambos cria dependências redundantes e dois caminhos de API para o mesmo recurso.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@prompts/plano-implementacao-testes-react.md` around lines 120 - 126, Remova a recomendação de instalar o pacote deprecated `@testing-library/react-hooks` do plano; mantenha apenas a instrução de instalar jest-axe. Concretamente, elimine a linha que sugere "npm install --save-dev `@testing-library/react-hooks`" e deixe a recomendação para usar o renderHook re-exportado por test-utils.tsx (o plano já usa renderHook via test-utils.tsx), para evitar dependências redundantes e caminhos duplicados para a mesma API.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/architecture.md`:
- Around line 2781-2829: The document currently presents React/Next.js +
NextAuth.js as the active stack while still showing legacy Blazor OIDC
components (AddOidcAuthentication, RemoteAuthenticatorView, App.razor) as if
they are current; update the auth section to reconcile this by explicitly
marking AddOidcAuthentication, RemoteAuthenticatorView and App.razor as
legacy/deprecated and clarifying that the current authentication flow uses
NextAuth.js with Keycloak OIDC for React/Next.js, or alternatively remove the
legacy Blazor snippets entirely and add a short migration note linking the
legacy components to their replacement in the NextAuth.js flow so there is a
single clearly identified "current" architecture.
In `@docs/roadmap-current.md`:
- Line 655: The roadmap notes that "**Mobile Apps**: De-scoped from MVP to Phase
2" but the Risks section still reserves Sprint 9 buffer for "MAUI Hybrid
Platform-Specific Issues"; update the Risks section to reflect the mobile
de-scope by removing or reprioritizing the "MAUI Hybrid Platform-Specific
Issues" risk in Sprint 9 and any other risk entries that assume mobile remains
in MVP, and adjust Sprint 9 buffer and risk priorities accordingly so the Mobile
Apps de-scope and Sprint 9 plan are consistent.
In `@prompts/plano-implementacao-testes-react.md`:
- Around line 252-298: Tests import renderHook from `@test-support` but the file
only wraps and exports render (not renderHook), so hooks that need
QueryClientProvider fail; add and export a wrapped renderHook that uses the same
AllTheProviders wrapper (or a wrapper factory that accepts a custom client from
createTestQueryClient) so hook tests run with React Query context. Specifically,
add a customRenderHook function that imports renderHook (and
RenderHookOptions/RenderHookResult types if needed) from the testing library,
calls renderHook(ui, { wrapper: AllTheProviders, ...options }), and export it
(e.g., export { customRenderHook as renderHook }) alongside the existing
exports; keep AllTheProviders and createTestQueryClient unchanged and reuse them
so both render and renderHook provide the QueryClientProvider.
- Around line 707-723: The CI test script "test:ci" currently runs vitest
without per-app configs; update the "test:ci" script in package.json to follow
the same per-project config pattern used by the other scripts (i.e., include
--config MeAjudaAi.Web.Customer/vitest.config.ts, --config
MeAjudaAi.Web.Admin/vitest.config.ts and --config
MeAjudaAi.Web.Provider/vitest.config.ts) and keep the desired reporters/coverage
flags (--coverage --reporter=junit --reporter=json-summary) so each app's
setupFiles, include patterns and coverage settings are loaded; modify the
"test:ci" entry accordingly (or run vitest sequentially for each config like the
"test" script but with the CI reporters).
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 56-64: The PerformanceObserver callback currently picks the first
LCP candidate via entries.find(...), which underestimates LCP; change the logic
in the PerformanceObserver callback (the observer handling in the
e2e/performance.spec.ts where variables resolved, entries, lcpEntry and
resolve({ lcp: ... }) are used) to select the last entry from list.getEntries()
(e.g., entries[entries.length - 1] or equivalent) as the lcpEntry before setting
resolved, disconnecting the observer, and calling resolve so the true, final LCP
value is recorded.
---
Duplicate comments:
In `@docs/architecture.md`:
- Around line 3176-3204: The documented E2E tree and Playwright config are
pointing to nonexistent locations (e.g., "src/MeAjudaAi.Web.Admin/e2e" and
testDir: './src') whereas the repo uses "src/Web/MeAjudaAi.Web.Admin/e2e",
"src/Web/MeAjudaAi.Web.Customer/e2e", "src/Web/MeAjudaAi.Web.Provider/e2e" and
"src/Web/libs/e2e-support/base.ts"; update the architecture.md snippet to show
the actual directories (replace top-level "src/" with "src/Web/") and adjust the
Playwright config example (change testDir from './src' to './src/Web' and update
any baseDir/baseURL notes referencing the old paths) so the documentation
matches the real repo layout and the exported helper reference (base.ts) points
to src/Web/libs/e2e-support/base.ts.
In `@docs/roadmap-current.md`:
- Around line 35-40: O bloco "Admin Portal (React - migrado na Sprint 8D)"
indica migração completa, mas o restante do documento ainda contém
narrativas/tabelas referindo-se a Blazor; corrija a inconsistência atualizando o
texto em docs/roadmap-current.md para refletir o estado real: ou marcar a
migração como "parcial" e documentar os componentes ainda em Blazor, ou remover
todas as referências a Blazor e ajustar as tabelas/narrativas subsequentes para
React/TypeScript; busque e atualize as seções que mencionam "Blazor", "Admin
Portal" e qualquer tabela de status para que todas usem o mesmo estado
(migrado/parcial) e linguagem consistente.
- Around line 624-631: The roadmap text references nonexistent test project
paths ("tests/MeAjudaAi.Web.*.Tests/e2e/") while the PR added E2E suites under
the actual projects (e.g., "src/Web/MeAjudaAi.Web.Customer/e2e",
"src/Web/MeAjudaAi.Web.Provider/e2e", "src/Web/MeAjudaAi.Web.Admin/e2e"); update
the Scope bullets (Playwright/Implement Test Specs/Customer/Provider/Admin
entries and Shared Fixtures/CI Integration notes) to use the real project
identifiers and correct e2e directories so the roadmap matches the implemented
locations.
In `@src/Web/MeAjudaAi.Web.Admin/auth.ts`:
- Around line 13-19: The current auth bootstrap silently falls back to
placeholder/localhost Keycloak values outside CI and never uses getRequiredEnv;
change it to fail fast by using getRequiredEnv to read required Keycloak
variables (e.g., KEYCLOAK_BASE_URL, KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID) instead
of injecting defaults, and only allow dummy fallbacks when process.env.CI is
explicitly truthy; update the Keycloak init code paths that currently set
placeholder values to call getRequiredEnv (or conditionally allow dummy values
when CI) so missing secrets throw an error at startup outside CI.
In `@src/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.ts`:
- Around line 166-170: The test "should display loading state while fetching
data" swallows assertion failures by using .catch(() => {}); remove the .catch
and instead simulate a delayed API response (use page.route or network mocking
for the dashboard data) so the loading spinner at locator
'[data-testid="dashboard-loading"]' is actually shown, then assert with await
expect(loadingSpinner).toBeVisible({ timeout: 10000 }) (no .catch) so the test
fails correctly if the spinner never appears.
- Around line 145-157: The test "should refresh data on button click" currently
asserts that kpiValueLocator (data-testid="kpi-total-providers") changes, which
can be flaky; update the test to verify a reliable indicator instead: use the
refreshButton locator (data-testid="refresh-dashboard") to trigger the action
and then assert either that the last-updated element (e.g.
[data-testid="last-updated"]) textContent changed or that the network refresh
request completed by intercepting the refresh API call; modify the test to
capture the pre-refresh last-updated value (or wait for the mocked network
route) and then after refresh click wait for the updated last-updated value (or
for the routed response) and assert it changed or that the route was called,
replacing the unreliable kpiValueLocator assertion.
In `@src/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.ts`:
- Around line 135-166: The CLS windowing logic under validEntries (variables
maxCls, currentWindowSum, windowStartTime) is incorrect because it resets based
on windowStartTime only; update it to follow the official CLS session rules:
iterate sorted validEntries and start a new session when the gap between the
current entry and the previous entry is >= 1000ms OR the current entry's
startTime minus the session's windowStartTime is >= 5000ms; track lastEntryTime
(previousStart) to check the 1s gap, update windowStartTime only when starting a
new session, accumulate currentWindowSum otherwise, and update maxCls whenever
you start a new session or at the end. Use the existing validEntries, maxCls,
currentWindowSum, windowStartTime names to locate and replace the windowing
logic.
- Around line 83-125: The PerformanceObserver is registered too late because the
test triggers page.click before the observer can capture the interaction; modify
the test "should meet INP threshold" so the observer is created and
observer.observe(...) is called before the user interaction, then trigger the
click from within the page.evaluate block (or otherwise ensure page.click runs
only after the observer resolves registration), set observer.observe to include
durationThreshold: 0 and buffered: true (e.g. observer.observe({ type: 'event',
buffered: true, durationThreshold: 0 })), and keep the fallback setTimeout
logic; update references to the observer, metrics, and the setTimeout timeout if
needed to ensure short interactions are captured and the promise resolves
correctly.
---
Nitpick comments:
In `@prompts/plano-implementacao-testes-react.md`:
- Around line 120-126: Remova a recomendação de instalar o pacote deprecated
`@testing-library/react-hooks` do plano; mantenha apenas a instrução de instalar
jest-axe. Concretamente, elimine a linha que sugere "npm install --save-dev
`@testing-library/react-hooks`" e deixe a recomendação para usar o renderHook
re-exportado por test-utils.tsx (o plano já usa renderHook via test-utils.tsx),
para evitar dependências redundantes e caminhos duplicados para a mesma API.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 37857e05-b218-47ab-b625-6d4202d5c1c8
📒 Files selected for processing (9)
docs/admin-portal/overview.mddocs/architecture.mddocs/roadmap-current.mdprompts/plano-implementacao-testes-react.mdsrc/Web/MeAjudaAi.Web.Admin/auth.tssrc/Web/MeAjudaAi.Web.Admin/e2e/dashboard.spec.tssrc/Web/MeAjudaAi.Web.Admin/e2e/mobile-responsiveness.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/performance.spec.tssrc/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts
✅ Files skipped from review due to trivial changes (1)
- src/Web/MeAjudaAi.Web.Customer/e2e/profile.spec.ts
… web applications with a shared test-support library.
…n resolver, database exceptions, and global exception handler
…s, and CI pipeline with coverage documentation
…cking and utility helpers
… and configure backend CI workflow
|
@coderabbitai could you review the last 30 commits, please? |
🧩 Analysis chain🏁 Script executed: Length of output: 5310
This is the complete history of the PR. Triggering a full review now to cover all 30 commits. 🧠 Learnings used✅ Actions performedFull review triggered. |
|
@coderabbitai the last commit is [44dfe4c], I want that you review from this one back to this [06f096e], every commit between these two |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 6930
🏁 Script executed: Length of output: 525
🏁 Script executed: Length of output: 20916 🏁 Script executed: Length of output: 11632
🏁 Script executed: Length of output: 13350 🏁 Script executed: Length of output: 44969
Revisão:
|
| Arquivo | Cenários |
|---|---|
RegisterProviderCommandHandlerTests.cs |
Success, user não encontrado, provider já existente |
ProviderServiceAddedDomainEventHandlerTests.cs |
Event handler dispatch |
ProviderServiceRemovedDomainEventHandlerTests.cs |
Event handler dispatch |
ProviderEventMappersTests.cs |
Mapeamentos completos |
ProviderServicesUpdatedIntegrationEventHandlerTests.cs |
SearchProviders infra |
DomainEventMapperExtensionsTests.cs |
Mapeamento de eventos de domínio |
LocalDevelopmentAuthenticationDomainServiceTests.cs |
Auth service local dev |
LocalDevelopmentUserDomainServiceTests.cs |
User service local dev |
✅ Headers AAA em inglês, conforme padrão do repositório.
📦 Grupo 3 — BusinessMetrics (14fa7ea)
✅ Bom: interval injetável via parâmetro opcional no MetricsCollectorService é o padrão correto para testabilidade.
✅ 3 arquivos de teste bem estruturados com MeterListener para validar métricas sem acoplamento ao runtime.
🔴 Problema: BusinessMetrics, BusinessMetricsMiddleware e MetricsCollectorService foram alterados de internal para public apenas para viabilizar os testes. Isso expõe implementações internas desnecessariamente. O correto é usar InternalsVisibleTo:
// Em src/Shared/AssemblyInfo.cs (ou no .csproj)
[assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")]Assim as classes permanecem internal e os testes do assembly de teste as enxergam normalmente.
📦 Grupo 4 — [ExcludeFromCodeCoverage] em Options/DTOs (d72ce57, 8183208)
✅ Estratégia correta e bem documentada — decorar classes Options/DTOs com [ExcludeFromCodeCoverage] é preferível a wildcards no YAML do CI, pois é autodocumentado no código.
✅ Classes bem selecionadas: CacheOptions, RabbitMqOptions, MessageBusOptions, DeadLetterOptions, PostgresOptions, KeycloakPermissionOptions, DTOs internos Keycloak, MessagingConfiguration.
🟡 Caractere estranho em docs/testing/coverage.md (commit d72ce57f):
para管理 coverage
O caractere 管理 (chinês, significa "gerenciar") foi inserido acidentalmente — provavelmente via autocomplete ou geração assistida. Corrigir para:
para gerenciar o coverage📦 Grupo 5 — Contracts Models (4a60abe)
✅ [ExcludeFromCodeCoverage] em todos os modelos Response<T>, PagedResult<T>, PagedResponse<T>, ApiErrorResponse, ValidationErrorResponse — correto para DTOs sem lógica de negócio.
🟡 Removido <remarks> de ValidationErrorResponse.cs junto com a adição do atributo. A documentação era útil — considere mantê-la separada do atributo (o atributo não implica remoção de doc).
📦 Grupo 6 — Testes de Middlewares de Segurança (1a5815b)
✅ Excelente — CompressionSecurityMiddlewareTests.cs (323 linhas) e ContentSecurityPolicyMiddlewareTests.cs (237 linhas) cobrem os middlewares que estavam completamente sem testes. Cenários abrangentes incluindo headers de segurança e respostas condicionais.
📦 Grupo 7 — SimpleHostEnvironment + Extension Tests (44dfe4c)
✅ [ExcludeFromCodeCoverage] em SimpleHostEnvironment — correto, é uma implementação interna de infraestrutura.
✅ HttpContextExtensionsTests.cs — excelente, cobre 7 cenários incluindo null accessor, múltiplas identities, fallback de claims vazias.
✅ DatabaseExtensionsTests.cs — cobre o registro do AddPostgres via DI.
🟡 Missing newline at end of file em ambos os novos arquivos de teste (indicado pelo \ No newline at end of file no diff). Adicionar quebra de linha final é boa prática e evita warnings em alguns editores.
Resumo Executivo
| Commit(s) | Severidade | Observação |
|---|---|---|
14fa7eaa |
🔴 Moderado | internal → public para testabilidade — usar InternalsVisibleTo |
d72ce57f |
🟡 Menor | Caractere 管理 em docs Portuguese |
4a60abe6 |
🟡 Menor | Remoção acidental de <remarks> em ValidationErrorResponse |
5cbeb411 |
🟡 Menor | find | while read subshell — funciona mas frágil |
44dfe4cd |
🟢 Menor | Missing newline nos 2 arquivos de teste |
6d2c2216 |
✅ | 8 novos testes de backend — exatamente as lacunas mapeadas |
d72ce57f / 81832089 |
✅ | Estratégia [ExcludeFromCodeCoverage] bem implementada |
1a5815bc |
✅ | Testes de middleware de segurança abrangentes |
| CI group | ✅ | Pipeline convergiu em estado estável |
✏️ Learnings added
Learnt from: frigini
URL: https://github.com/frigini/MeAjudaAi/pull/182
Timestamp: 2026-04-07T22:57:34.721Z
Learning: In the MeAjudaAi codebase, when internal classes in src/Shared (e.g., BusinessMetrics, BusinessMetricsMiddleware, MetricsCollectorService) are made public solely for test visibility, the preferred approach is to use `[assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")]` in the Shared project instead, keeping the classes `internal`. This preserves encapsulation while allowing test access.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:65-77
Timestamp: 2025-12-18T00:35:33.829Z
Learning: MeAjudaAi repo: Exceção à política de idioma para comentários — em testes, os cabeçalhos AAA (Arrange, Act, Assert) devem permanecer em inglês e não devem ser traduzidos. Comentários/XML continuam em português; logs em inglês; mensagens ao usuário (validações/APIs) em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:48-63
Timestamp: 2025-12-18T00:36:23.299Z
Learning: Nos testes do repositório MeAjudaAi, os rótulos do padrão AAA (Arrange/Act/Assert) devem permanecer em inglês e não devem ser traduzidos para português, mesmo que comentários e XML docs sejam em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T21:50:23.593Z
Learning: For frigini/MeAjudaAi Web reviews, prefer commit-by-commit (newest-first) with concise verdicts and concrete follow-ups; prioritize reuse of Shared.Contracts for enums/constants to keep Web aligned with backend/shared code.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:26:37.409Z
Learning: MeAjudaAi logging policy: logs must be in English, comments may remain in Portuguese. Portuguese logs were additionally found in Users (API/Extensions.cs:83), Providers (API/Extensions.cs:74), ServiceCatalogs (API/Extensions.cs:78,86,93), and Locations (multiple clients/services lines listed). SearchProviders module currently has no Portuguese logs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:09:54.585Z
Learning: In the MeAjudaAi codebase, when reviewing log messages in application handlers, verify they are in English. The file src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs had Portuguese logs that violated the English-only logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:32:51.210Z
Learning: Além de manter logs em inglês, os comentários e a documentação XML (/// <summary>, <param>, etc.) devem ser escritos em português em todo o código MeAjudaAi.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Locations/API/Endpoints/GetAllowedCityByIdEndpoint.cs:38-38
Timestamp: 2025-12-17T21:10:58.245Z
Learning: In the MeAjudaAi codebase, there are three distinct language standards: (1) Logs must be in English, (2) Comments and XML summaries (///, <summary>, <param>, etc.) must be in Portuguese, (3) User-facing validation messages and API responses shown to the frontend must be in Portuguese. User-facing messages include error responses like Results.NotFound, Results.BadRequest, and constants in ValidationMessages.cs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 29
File: tests/MeAjudaAi.Shared.Tests/Middleware/GeographicRestrictionMiddlewareTests.cs:178-178
Timestamp: 2025-11-25T01:05:52.410Z
Learning: In the MeAjudaAi codebase, the standard for comments is Portuguese (due to the Brazilian team), and English is only required for logs. Do not suggest changing Portuguese comments to English.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:18:43.521Z
Learning: In the MeAjudaAi codebase, Portuguese log messages were found across 9 files: Documents module handlers/ModuleApi/Jobs (35+ logs), Shared Jobs/Seeding/RabbitMq (7 logs), and integration test infrastructure (5 logs). The Documents module is the primary violator with most Portuguese logs requiring translation to English per the logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T19:53:35.881Z
Learning: When the repository owner asks for “commit reviews,” prefer a commit-by-commit review (newest-first), with concise verdicts and specific follow-ups, rather than only a PR-wide summary.
…dels, and foundational extension tests
|
@coderabbitai please review the commit [c9cb4d4], I am trying to adjust the code coverage by adding new tests and exclusions to achieve 90% of coverage |
|
@coderabbitai please review the commit c9cb4d4, I am trying to adjust the code coverage by adding new tests and exclusions to achieve 90% of coverage |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 2250 🏁 Script executed: Length of output: 1507 🏁 Script executed: Length of output: 18047
Revisão do Commit
|
| Problema anterior | Status |
|---|---|
find | while read subshell no CI |
✅ Corrigido com mapfile -t |
Caractere 管理 em docs/testing/coverage.md |
✅ Corrigido para gerenciar |
<remarks> removido de ValidationErrorResponse |
✅ Restaurado |
using System.Diagnostics.CodeAnalysis faltando nos Contracts |
✅ Adicionado em todos os 4 arquivos |
BusinessMetrics* público desnecessariamente |
✅ Revertido para internal |
Testes de fallback faltando em DatabaseExtensionsTests |
✅ +8 novos testes de cobertura |
🔴 Verificação necessária — internal sem InternalsVisibleTo
BusinessMetrics, BusinessMetricsMiddleware e MetricsCollectorService voltaram para internal. Se os testes de BusinessMetricsTests.cs (adicionados em 14fa7eaa) instanciam essas classes diretamente, eles vão falhar em compilar agora. Verifique:
// Em src/Shared/MeAjudaAi.Shared.csproj ou AssemblyInfo.cs
[assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")]Se os testes acessam as classes via DI (resolvendo por IHostedService, IMiddleware, etc.) sem referenciar os tipos concretos, está tudo certo. Caso contrário, o InternalsVisibleTo é obrigatório.
🟡 ValidationExtensionsTests.cs — SingleOrDefault instável
// Linha 43 — PROBLEMÁTICO se houver mais de um IPipelineBehavior<,> registrado
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(MeAjudaAi.Shared.Mediator.IPipelineBehavior<,>));
descriptor.Should().NotBeNull();SingleOrDefault lança InvalidOperationException se houver múltiplas registrações (ex.: ValidationBehavior<,> + CachingBehavior<,>). Prefira:
// Opção 1 - verificar se existe pelo menos um
var hasValidationBehavior = services.Any(d =>
d.ServiceType == typeof(IPipelineBehavior<,>) &&
d.ImplementationType?.Name.Contains("Validation") == true);
hasValidationBehavior.Should().BeTrue();
// Opção 2 - usar FirstOrDefault
var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IPipelineBehavior<,>));
descriptor.Should().NotBeNull();🟡 PermissionHealthCheckExtensionsTests.cs — assertiva trivialmente verdadeira
public void AddPermissionSystemHealthCheck_WithValidServices_ShouldAddHealthCheck()
{
var services = new ServiceCollection();
var result = services.AddPermissionSystemHealthCheck();
result.Should().BeSameAs(services);
services.Should().NotBeEmpty(); // ← TRIVIAL: sempre true após qualquer AddXxx
}O services.Should().NotBeEmpty() não valida nada específico — qualquer chamada a qualquer AddXxx tornaria o ServiceCollection não-vazio. Considere:
// Verificar se o health check foi especificamente registrado
var hasHealthCheck = services.Any(d =>
d.ServiceType.Name.Contains("HealthCheck") ||
d.ImplementationType?.Name.Contains("Permission") == true);
hasHealthCheck.Should().BeTrue();🟡 ModuleServiceRegistrationExtensionsTests.cs — smoke tests sem assertivas de registro real
Os 12 testes cobrem apenas null-guard e "não lança exceção". Para cobertura de linhas isso é suficiente, mas os testes não detectariam uma quebra de comportamento (ex.: se AddModuleValidators parasse de registrar validators). Considere adicionar ao menos um teste com assertiva concreta:
[Fact]
public void AddModuleValidators_ShouldRegisterAtLeastOneValidator()
{
// Arrange
var services = new ServiceCollection();
// Act
services.AddModuleValidators(typeof(SomeKnownValidator).Assembly);
// Assert
services.Should().Contain(d => d.Lifetime == ServiceLifetime.Scoped);
}🟢 Minor — DatabaseExtensionsTests.cs — newline faltando no final do arquivo
O arquivo termina com } sem quebra de linha final (indicado pelo \ No newline at end of file). Adicionar é boa prática e evita warnings em alguns editores/analisadores.
✅ DatabaseExtensionsTests.cs — Excelente expansão
Os 8 novos testes cobrem toda a cadeia de fallback de connection string (DefaultConnection → meajudaai-db-local → meajudaai-db → Postgres:ConnectionString → empty em Testing) e os registros de DI (Dapper, SchemaPermissionsManager, Singleton). Abordagem correta.
Resumo
| Arquivo | Severidade | Ação |
|---|---|---|
BusinessMetrics*.cs + testes |
🔴 Verificar | Confirmar se testes compilam com internal ou adicionar InternalsVisibleTo |
ValidationExtensionsTests.cs |
🟡 | Trocar SingleOrDefault por Any() ou FirstOrDefault() |
PermissionHealthCheckExtensionsTests.cs |
🟡 | Substituir assertiva trivial por verificação de registro específico |
ModuleServiceRegistrationExtensionsTests.cs |
🟡 | Adicionar ao menos uma assertiva de registro real |
DatabaseExtensionsTests.cs |
🟢 | Adicionar newline no final do arquivo |
🧠 Learnings used
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:65-77
Timestamp: 2025-12-18T00:35:33.829Z
Learning: MeAjudaAi repo: Exceção à política de idioma para comentários — em testes, os cabeçalhos AAA (Arrange, Act, Assert) devem permanecer em inglês e não devem ser traduzidos. Comentários/XML continuam em português; logs em inglês; mensagens ao usuário (validações/APIs) em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:48-63
Timestamp: 2025-12-18T00:36:23.299Z
Learning: Nos testes do repositório MeAjudaAi, os rótulos do padrão AAA (Arrange/Act/Assert) devem permanecer em inglês e não devem ser traduzidos para português, mesmo que comentários e XML docs sejam em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T21:50:23.593Z
Learning: For frigini/MeAjudaAi Web reviews, prefer commit-by-commit (newest-first) with concise verdicts and concrete follow-ups; prioritize reuse of Shared.Contracts for enums/constants to keep Web aligned with backend/shared code.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:26:37.409Z
Learning: MeAjudaAi logging policy: logs must be in English, comments may remain in Portuguese. Portuguese logs were additionally found in Users (API/Extensions.cs:83), Providers (API/Extensions.cs:74), ServiceCatalogs (API/Extensions.cs:78,86,93), and Locations (multiple clients/services lines listed). SearchProviders module currently has no Portuguese logs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:09:54.585Z
Learning: In the MeAjudaAi codebase, when reviewing log messages in application handlers, verify they are in English. The file src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs had Portuguese logs that violated the English-only logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:32:51.210Z
Learning: Além de manter logs em inglês, os comentários e a documentação XML (/// <summary>, <param>, etc.) devem ser escritos em português em todo o código MeAjudaAi.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Locations/API/Endpoints/GetAllowedCityByIdEndpoint.cs:38-38
Timestamp: 2025-12-17T21:10:58.245Z
Learning: In the MeAjudaAi codebase, there are three distinct language standards: (1) Logs must be in English, (2) Comments and XML summaries (///, <summary>, <param>, etc.) must be in Portuguese, (3) User-facing validation messages and API responses shown to the frontend must be in Portuguese. User-facing messages include error responses like Results.NotFound, Results.BadRequest, and constants in ValidationMessages.cs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 29
File: tests/MeAjudaAi.Shared.Tests/Middleware/GeographicRestrictionMiddlewareTests.cs:178-178
Timestamp: 2025-11-25T01:05:52.410Z
Learning: In the MeAjudaAi codebase, the standard for comments is Portuguese (due to the Brazilian team), and English is only required for logs. Do not suggest changing Portuguese comments to English.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:18:43.521Z
Learning: In the MeAjudaAi codebase, Portuguese log messages were found across 9 files: Documents module handlers/ModuleApi/Jobs (35+ logs), Shared Jobs/Seeding/RabbitMq (7 logs), and integration test infrastructure (5 logs). The Documents module is the primary violator with most Portuguese logs requiring translation to English per the logging policy.
|
Tip For best results, initiate chat on the files or code changes.
Key Findings for
|
| Severity | File | Issue |
|---|---|---|
| 🔴 Verify | BusinessMetrics*.cs + tests |
Classes reverted to internal — confirm tests still compile, or add [assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")] |
| 🟡 Fix | ValidationExtensionsTests.cs |
SingleOrDefault will throw if multiple IPipelineBehavior<,> are registered — use Any() or FirstOrDefault() instead |
| 🟡 Improve | PermissionHealthCheckExtensionsTests.cs |
services.Should().NotBeEmpty() is trivially true — assert a specific health check registration |
| 🟡 Improve | ModuleServiceRegistrationExtensionsTests.cs |
Smoke-only tests won't catch behavioral regressions — add at least one concrete registration assertion |
| 🟢 Minor | DatabaseExtensionsTests.cs |
Missing newline at end of file |
✅ All previous issues were resolved: mapfile -t in CI, 管理 character in docs, <remarks> restored, using directives in Contracts, BusinessMetrics* back to internal, and 8 new DatabaseExtensionsTests.
The highest priority action is verifying the InternalsVisibleTo situation — if BusinessMetricsTests.cs directly instantiates BusinessMetrics, BusinessMetricsMiddleware, or MetricsCollectorService, the build will fail now that they're internal again. Add this to src/Shared/MeAjudaAi.Shared.csproj or a AssemblyInfo.cs:
[assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")]🧠 Learnings used
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:65-77
Timestamp: 2025-12-18T00:35:33.829Z
Learning: MeAjudaAi repo: Exceção à política de idioma para comentários — em testes, os cabeçalhos AAA (Arrange, Act, Assert) devem permanecer em inglês e não devem ser traduzidos. Comentários/XML continuam em português; logs em inglês; mensagens ao usuário (validações/APIs) em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:48-63
Timestamp: 2025-12-18T00:36:23.299Z
Learning: Nos testes do repositório MeAjudaAi, os rótulos do padrão AAA (Arrange/Act/Assert) devem permanecer em inglês e não devem ser traduzidos para português, mesmo que comentários e XML docs sejam em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T21:50:23.593Z
Learning: For frigini/MeAjudaAi Web reviews, prefer commit-by-commit (newest-first) with concise verdicts and concrete follow-ups; prioritize reuse of Shared.Contracts for enums/constants to keep Web aligned with backend/shared code.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:26:37.409Z
Learning: MeAjudaAi logging policy: logs must be in English, comments may remain in Portuguese. Portuguese logs were additionally found in Users (API/Extensions.cs:83), Providers (API/Extensions.cs:74), ServiceCatalogs (API/Extensions.cs:78,86,93), and Locations (multiple clients/services lines listed). SearchProviders module currently has no Portuguese logs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:09:54.585Z
Learning: In the MeAjudaAi codebase, when reviewing log messages in application handlers, verify they are in English. The file src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs had Portuguese logs that violated the English-only logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:32:51.210Z
Learning: Além de manter logs em inglês, os comentários e a documentação XML (/// <summary>, <param>, etc.) devem ser escritos em português em todo o código MeAjudaAi.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Locations/API/Endpoints/GetAllowedCityByIdEndpoint.cs:38-38
Timestamp: 2025-12-17T21:10:58.245Z
Learning: In the MeAjudaAi codebase, there are three distinct language standards: (1) Logs must be in English, (2) Comments and XML summaries (///, <summary>, <param>, etc.) must be in Portuguese, (3) User-facing validation messages and API responses shown to the frontend must be in Portuguese. User-facing messages include error responses like Results.NotFound, Results.BadRequest, and constants in ValidationMessages.cs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 29
File: tests/MeAjudaAi.Shared.Tests/Middleware/GeographicRestrictionMiddlewareTests.cs:178-178
Timestamp: 2025-11-25T01:05:52.410Z
Learning: In the MeAjudaAi codebase, the standard for comments is Portuguese (due to the Brazilian team), and English is only required for logs. Do not suggest changing Portuguese comments to English.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:18:43.521Z
Learning: In the MeAjudaAi codebase, Portuguese log messages were found across 9 files: Documents module handlers/ModuleApi/Jobs (35+ logs), Shared Jobs/Seeding/RabbitMq (7 logs), and integration test infrastructure (5 logs). The Documents module is the primary violator with most Portuguese logs requiring translation to English per the logging policy.
…ring, and associated unit tests
|
@coderabbitai now please review the commit c7883fa please |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 15812
Revisão do Commit
|
| Problema (c9cb4d4) | Status |
|---|---|
SingleOrDefault em ValidationExtensionsTests |
✅ Substituído por Any() + filtro de nome |
Assertiva trivial em PermissionHealthCheckExtensionsTests |
✅ Substituída por verificação de registro específico |
Smoke-only em ModuleServiceRegistrationExtensionsTests |
✅ Adicionado AddModuleValidators_ShouldRegisterAtLeastOneValidator com DummyValidator real |
DatabaseExtensionsTests com Mock<IConfiguration> |
✅ Migrado para ConfigurationBuilder + AddInMemoryCollection — muito mais robusto |
KeycloakPermissionResolverTests nullable warning |
✅ Corrigido com null! |
🔴 Problema — BusinessMetrics* voltou para public novamente
// c9cb4d4 reverteu para internal
-internal class BusinessMetrics : IDisposable
+public class BusinessMetrics : IDisposable // ← c7883fa voltou para publicNeste commit o InternalsVisibleTo("DynamicProxyGenAssembly2") foi adicionado corretamente ao .csproj — esse é exatamente o entry necessário para o Moq criar proxies de tipos internos. Combinado com o InternalsVisibleTo("MeAjudaAi.Shared.Tests") que já existia, as três classes deveriam permanecer internal sem nenhuma mudança adicional nos testes.
Correção recomendada — reverter os 3 arquivos de public para internal:
// src/Shared/Monitoring/BusinessMetrics.cs
internal class BusinessMetrics : IDisposable { ... }
// src/Shared/Monitoring/BusinessMetricsMiddleware.cs
internal class BusinessMetricsMiddleware(...) { ... }
// src/Shared/Monitoring/MetricsCollectorService.cs
internal class MetricsCollectorService(...) { ... }O .csproj com os dois InternalsVisibleTo já está correto:
<InternalsVisibleTo Include="MeAjudaAi.Shared.Tests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />🟡 AnalysisMode=All + EnforceCodeStyleInBuild=true podem quebrar o CI
<AnalysisMode>All</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>AnalysisMode=All ativa todas as regras de análise, incluindo categorias Design, Naming, Performance, Reliability. Se houver violações existentes no projeto Shared (muito provável), o build vai falhar mesmo em código não tocado por esta PR. Recomendação: começar com AnalysisMode=Recommended ou usar um .editorconfig para suprimir regras específicas antes de ativar o modo All.
✅ DatabaseExtensionsTests.cs — Excelente refactoring
A migração de Mock<IConfiguration> para ConfigurationBuilder real é a abordagem correta — testa o comportamento real de resolução de configuração (GetConnectionString → GetSection → fallback) em vez de mockar um contrato que pode ser chamado de formas diferentes internamente. Também corrigiu a definição de TestDbContext para usar primary constructor.
🟢 Minor: ainda falta newline no final do arquivo (o } da última linha não tem \n após ele).
✅ ModuleServiceRegistrationExtensionsTests.cs — assertiva concreta correta
services.Should().Contain(d => d.ServiceType.Name.Contains("IValidator"));Valida o registro real de validators. O DummyValidator como inner class do test é o padrão correto para assembly-scanning.
Resumo
| Arquivo | Severidade | Ação |
|---|---|---|
BusinessMetrics*.cs (3 arquivos) |
🔴 | Reverter para internal — InternalsVisibleTo já está correto no .csproj |
MeAjudaAi.Shared.csproj |
🟡 | AnalysisMode=All pode quebrar build em código existente — considerar Recommended |
DatabaseExtensionsTests.cs |
🟢 | Newline faltando no EOF |
🧠 Learnings used
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:65-77
Timestamp: 2025-12-18T00:35:33.829Z
Learning: MeAjudaAi repo: Exceção à política de idioma para comentários — em testes, os cabeçalhos AAA (Arrange, Act, Assert) devem permanecer em inglês e não devem ser traduzidos. Comentários/XML continuam em português; logs em inglês; mensagens ao usuário (validações/APIs) em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:48-63
Timestamp: 2025-12-18T00:36:23.299Z
Learning: Nos testes do repositório MeAjudaAi, os rótulos do padrão AAA (Arrange/Act/Assert) devem permanecer em inglês e não devem ser traduzidos para português, mesmo que comentários e XML docs sejam em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T21:50:23.593Z
Learning: For frigini/MeAjudaAi Web reviews, prefer commit-by-commit (newest-first) with concise verdicts and concrete follow-ups; prioritize reuse of Shared.Contracts for enums/constants to keep Web aligned with backend/shared code.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:26:37.409Z
Learning: MeAjudaAi logging policy: logs must be in English, comments may remain in Portuguese. Portuguese logs were additionally found in Users (API/Extensions.cs:83), Providers (API/Extensions.cs:74), ServiceCatalogs (API/Extensions.cs:78,86,93), and Locations (multiple clients/services lines listed). SearchProviders module currently has no Portuguese logs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:09:54.585Z
Learning: In the MeAjudaAi codebase, when reviewing log messages in application handlers, verify they are in English. The file src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs had Portuguese logs that violated the English-only logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:32:51.210Z
Learning: Além de manter logs em inglês, os comentários e a documentação XML (/// <summary>, <param>, etc.) devem ser escritos em português em todo o código MeAjudaAi.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Locations/API/Endpoints/GetAllowedCityByIdEndpoint.cs:38-38
Timestamp: 2025-12-17T21:10:58.245Z
Learning: In the MeAjudaAi codebase, there are three distinct language standards: (1) Logs must be in English, (2) Comments and XML summaries (///, <summary>, <param>, etc.) must be in Portuguese, (3) User-facing validation messages and API responses shown to the frontend must be in Portuguese. User-facing messages include error responses like Results.NotFound, Results.BadRequest, and constants in ValidationMessages.cs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 29
File: tests/MeAjudaAi.Shared.Tests/Middleware/GeographicRestrictionMiddlewareTests.cs:178-178
Timestamp: 2025-11-25T01:05:52.410Z
Learning: In the MeAjudaAi codebase, the standard for comments is Portuguese (due to the Brazilian team), and English is only required for logs. Do not suggest changing Portuguese comments to English.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:18:43.521Z
Learning: In the MeAjudaAi codebase, Portuguese log messages were found across 9 files: Documents module handlers/ModuleApi/Jobs (35+ logs), Shared Jobs/Seeding/RabbitMq (7 logs), and integration test infrastructure (5 logs). The Documents module is the primary violator with most Portuguese logs requiring translation to English per the logging policy.
|
@coderabbitai Even with InternalsVisibleTo, Moq is still facing persistent issues (21 failures) when trying to instantiate these classes via proxy, especially due to the use of primary constructors and generic loggers (ILogger). Changing them to public removes this visibility barrier and definitively resolves the proxy failures, following a suggestion you previously mentioned to avoid visibility anti-patterns. Do you agree with this change? What do you suggest? Another point: which Shared code do I have to add testes to make the coverage increase? |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 37816
1.
|
| Arquivo | Linhas | Complexidade | Tipo de teste |
|---|---|---|---|
SchemaPermissionsManager.cs |
180 | Média | Integração (requer DB) |
HangfireBackgroundJobService.cs |
153 | Média | Unit com Moq |
ServiceCollectionExtensions.cs |
134 | Baixa | Unit DI scan |
RabbitMqInfrastructureManager.cs |
98 | Alta | Unit com Moq |
HangfireExtensions.cs |
90 | Baixa | Unit DI registration |
DatabaseMetrics.cs |
88 | Baixa | Unit com MeterListener |
MessageBusFactory.cs |
76 | Baixa | Unit |
NoOpDeadLetterService.cs |
75 | Baixa | Unit — simples |
KeycloakPermissionProvider.cs |
66 | Média | Unit com Moq |
MonitoringExtensions.cs |
59 | Baixa | Unit DI registration |
UnprocessableEntityException.cs |
50 | Baixa | Unit — trivial |
MessageRetryExtensions.cs |
45 | Baixa | Unit |
EnvironmentHelpers.cs |
42 | Baixa | Unit |
ValueObject.cs |
32 | Baixa | Unit |
GeoPointConverter.cs |
27 | Baixa | Unit JSON |
SerializationDefaults.cs |
37 | Baixa | Unit |
Os três de maior retorno imediato:
NoOpDeadLetterServiceTests.cs (fácil, ~30 linhas)
[Trait("Category", "Unit")]
public class NoOpDeadLetterServiceTests
{
private readonly NoOpDeadLetterService _sut = new();
[Fact]
public async Task GetFailedMessagesAsync_ShouldReturnEmptyList()
{
// Act
var result = await _sut.GetFailedMessagesAsync();
// Assert
result.Should().BeEmpty();
}
[Fact]
public async Task RetryMessageAsync_ShouldReturnTrue()
{
// Act
var result = await _sut.RetryMessageAsync("any-id");
// Assert
result.Should().BeTrue();
}
[Fact]
public async Task GetStatisticsAsync_ShouldReturnEmptyStatistics()
{
// Act
var result = await _sut.GetStatisticsAsync();
// Assert
result.Should().NotBeNull();
}
}HangfireExtensionsTests.cs (médio, ~50 linhas)
[Trait("Category", "Unit")]
public class HangfireExtensionsTests
{
[Fact]
public void AddHangfire_ShouldRegisterHangfireServices()
{
// Arrange
var services = new ServiceCollection();
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["ConnectionStrings:DefaultConnection"] = "Host=localhost;Database=test"
}).Build();
// Act
services.AddHangfireServices(config);
// Assert
services.Should().Contain(d =>
d.ServiceType.Name.Contains("Hangfire") ||
d.ImplementationType?.Namespace?.Contains("Hangfire") == true);
}
}UnprocessableEntityExceptionTests.cs (trivial, ~20 linhas)
[Trait("Category", "Unit")]
public class UnprocessableEntityExceptionTests
{
[Fact]
public void Constructor_WithMessage_ShouldSetMessage()
{
// Arrange & Act
var ex = new UnprocessableEntityException("dados inválidos");
// Assert
ex.Message.Should().Be("dados inválidos");
}
[Fact]
public void Constructor_Default_ShouldInheritFromException()
{
// Assert
typeof(UnprocessableEntityException).Should().BeDerivedFrom<Exception>();
}
}Estratégia recomendada
Passo 1 (imediato): Adicionar [ExcludeFromCodeCoverage] nos ~15 arquivos de constantes/DTOs/design-time
→ ~700 linhas removidas da métrica, sem escrever um único teste
Passo 2 (curto prazo): NoOpDeadLetterService + UnprocessableEntityException + HangfireExtensions
→ ~300 linhas cobertas com ~100 linhas de teste
Passo 3 (médio prazo): ServiceCollectionExtensions + MonitoringExtensions + DatabaseMetrics
→ ~320 linhas adicionais cobertas
Passo 4 (opcional): HangfireBackgroundJobService + MessageBusFactory + KeycloakPermissionProvider
→ Requer mais setup de Moq, maior complexidade
O Passo 1 sozinho provavelmente já empurra a cobertura acima de 90% dado que a maioria das classes com lógica real já está testada.
✏️ Learnings added
Learnt from: frigini
URL: https://github.com/frigini/MeAjudaAi/pull/182
Timestamp: 2026-04-08T01:57:29.285Z
Learning: In the MeAjudaAi codebase, making BusinessMetrics, BusinessMetricsMiddleware, and MetricsCollectorService `public` (instead of `internal`) is the accepted approach when Moq proxy generation fails due to C# 12 primary constructors combined with generic loggers (ILogger<T>). Even with `InternalsVisibleTo("DynamicProxyGenAssembly2")`, Moq cannot reliably generate proxies for primary constructor types. The `public` visibility is justified because these classes are DI-registered infrastructure shared across modules.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:65-77
Timestamp: 2025-12-18T00:35:33.829Z
Learning: MeAjudaAi repo: Exceção à política de idioma para comentários — em testes, os cabeçalhos AAA (Arrange, Act, Assert) devem permanecer em inglês e não devem ser traduzidos. Comentários/XML continuam em português; logs em inglês; mensagens ao usuário (validações/APIs) em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:48-63
Timestamp: 2025-12-18T00:36:23.299Z
Learning: Nos testes do repositório MeAjudaAi, os rótulos do padrão AAA (Arrange/Act/Assert) devem permanecer em inglês e não devem ser traduzidos para português, mesmo que comentários e XML docs sejam em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T21:50:23.593Z
Learning: For frigini/MeAjudaAi Web reviews, prefer commit-by-commit (newest-first) with concise verdicts and concrete follow-ups; prioritize reuse of Shared.Contracts for enums/constants to keep Web aligned with backend/shared code.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:26:37.409Z
Learning: MeAjudaAi logging policy: logs must be in English, comments may remain in Portuguese. Portuguese logs were additionally found in Users (API/Extensions.cs:83), Providers (API/Extensions.cs:74), ServiceCatalogs (API/Extensions.cs:78,86,93), and Locations (multiple clients/services lines listed). SearchProviders module currently has no Portuguese logs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:09:54.585Z
Learning: In the MeAjudaAi codebase, when reviewing log messages in application handlers, verify they are in English. The file src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs had Portuguese logs that violated the English-only logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:32:51.210Z
Learning: Além de manter logs em inglês, os comentários e a documentação XML (/// <summary>, <param>, etc.) devem ser escritos em português em todo o código MeAjudaAi.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Locations/API/Endpoints/GetAllowedCityByIdEndpoint.cs:38-38
Timestamp: 2025-12-17T21:10:58.245Z
Learning: In the MeAjudaAi codebase, there are three distinct language standards: (1) Logs must be in English, (2) Comments and XML summaries (///, <summary>, <param>, etc.) must be in Portuguese, (3) User-facing validation messages and API responses shown to the frontend must be in Portuguese. User-facing messages include error responses like Results.NotFound, Results.BadRequest, and constants in ValidationMessages.cs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 29
File: tests/MeAjudaAi.Shared.Tests/Middleware/GeographicRestrictionMiddlewareTests.cs:178-178
Timestamp: 2025-11-25T01:05:52.410Z
Learning: In the MeAjudaAi codebase, the standard for comments is Portuguese (due to the Brazilian team), and English is only required for logs. Do not suggest changing Portuguese comments to English.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:18:43.521Z
Learning: In the MeAjudaAi codebase, Portuguese log messages were found across 9 files: Documents module handlers/ModuleApi/Jobs (35+ logs), Shared Jobs/Seeding/RabbitMq (7 logs), and integration test infrastructure (5 logs). The Documents module is the primary violator with most Portuguese logs requiring translation to English per the logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-04-07T22:57:34.721Z
Learning: In the MeAjudaAi codebase, when internal classes in src/Shared (e.g., BusinessMetrics, BusinessMetricsMiddleware, MetricsCollectorService) are made public solely for test visibility, the preferred approach is to use `[assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")]` in the Shared project instead, keeping the classes `internal`. This preserves encapsulation while allowing test access.
…onstants and adding unit tests
|
@coderabbitai please review the commit [31d08df] |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 16933
Revisão do Commit
|
| Grupo | Arquivos | Justificativa |
|---|---|---|
| Constantes | CacheTags, DatabaseConstants, ApiEndpoints, AuthConstants, EnvironmentNames, FeatureFlags, RateLimitPolicies, RoleConstants, ValidationConstants |
Static constants sem lógica |
| Integration Events | 11 sealed records |
DTOs puros de transporte de eventos |
| Design-time | BaseDesignTimeDbContextFactory |
Executa apenas durante dotnet ef migrations, nunca em produção |
Impacto estimado: ~700+ linhas removidas da métrica de cobertura, sem escrever um único teste adicional.
✅ UnprocessableEntityExceptionTests.cs — Correto
Implementação exata do esqueleto sugerido anteriormente. Dois cenários corretos, AAA em inglês, zero issues.
🔴 NoOpDeadLetterServiceTests.cs — Teste sem assertiva
O teste ShouldRetry_ShouldReturnTrueForLowAttemptCount computa result mas nunca o asserta:
[Theory]
[InlineData(1)]
[InlineData(3)]
public void ShouldRetry_ShouldReturnTrueForLowAttemptCount(int attemptCount)
{
var ex = new Exception("test");
// Act
var result = _sut.ShouldRetry(ex, attemptCount);
// Assert
// Nota: ClassifyFailure por padrão pode não retornar Transient para uma Exception genérica
// mas o NoOpDeadLetterService apenas checa a contagem se o classify permitir.
// ← NENHUMA ASSERTIVA! result é ignorado
}Este teste sempre passa, independentemente do comportamento real do método. O comentário em português reconhece a incerteza sobre o retorno, mas não resolve o problema. Sugestões:
Opção 1 — Se a exceção genérica não é classificada como Transient e retorna false:
// Assert
result.Should().BeFalse(); // Exception genérica não é Transient, retorna falseOpção 2 — Se o comportamento depende da classificação interna e é genuinamente incerto:
// Remover o Theory e testar apenas o caminho confirmado:
[Fact]
public void ShouldRetry_WithHighAttemptCount_ShouldReturnFalse()
{
var result = _sut.ShouldRetry(new Exception("test"), 10);
result.Should().BeFalse(); // Acima do threshold, sempre false
}Opção 3 — Criar um exception type específico que seja Transient:
[Theory]
[InlineData(1)]
[InlineData(3)]
public void ShouldRetry_WithTransientExceptionAndLowAttempt_ShouldReturnTrue(int attemptCount)
{
var ex = new TimeoutException("transient"); // TimeoutException geralmente é Transient
var result = _sut.ShouldRetry(ex, attemptCount);
result.Should().BeTrue();
}🟡 CalculateRetryDelay_ShouldReturnCorrectDelay — Acoplado à implementação
_sut.CalculateRetryDelay(1).TotalSeconds.Should().Be(2); // 2^(1-1) * 2 = 2
_sut.CalculateRetryDelay(2).TotalSeconds.Should().Be(4); // 2^(2-1) * 2 = 4
_sut.CalculateRetryDelay(10).TotalSeconds.Should().Be(300); // Max delayFunciona e as assertivas são concretas ✅. Só vale notar que se a fórmula de backoff mudar, o teste quebra — o que é um comportamento desejável de um teste de contrato. Sem problemas aqui.
Resumo
| Arquivo | Severidade | Ação |
|---|---|---|
NoOpDeadLetterServiceTests.cs — ShouldRetry_ShouldReturnTrueForLowAttemptCount |
🔴 | Adicionar assertiva concreta em result ou remover o teste |
21 arquivos com [ExcludeFromCodeCoverage] |
✅ | Estratégia correta — impacto imediato na métrica |
UnprocessableEntityExceptionTests.cs |
✅ | Implementação limpa e correta |
CalculateRetryDelay |
✅ | Assertivas concretas — ok |
🧠 Learnings used
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:65-77
Timestamp: 2025-12-18T00:35:33.829Z
Learning: MeAjudaAi repo: Exceção à política de idioma para comentários — em testes, os cabeçalhos AAA (Arrange, Act, Assert) devem permanecer em inglês e não devem ser traduzidos. Comentários/XML continuam em português; logs em inglês; mensagens ao usuário (validações/APIs) em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Providers/Tests/Unit/Application/Queries/GetProvidersByIdsQueryTests.cs:48-63
Timestamp: 2025-12-18T00:36:23.299Z
Learning: Nos testes do repositório MeAjudaAi, os rótulos do padrão AAA (Arrange/Act/Assert) devem permanecer em inglês e não devem ser traduzidos para português, mesmo que comentários e XML docs sejam em português.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-01-16T21:50:23.593Z
Learning: For frigini/MeAjudaAi Web reviews, prefer commit-by-commit (newest-first) with concise verdicts and concrete follow-ups; prioritize reuse of Shared.Contracts for enums/constants to keep Web aligned with backend/shared code.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:26:37.409Z
Learning: MeAjudaAi logging policy: logs must be in English, comments may remain in Portuguese. Portuguese logs were additionally found in Users (API/Extensions.cs:83), Providers (API/Extensions.cs:74), ServiceCatalogs (API/Extensions.cs:78,86,93), and Locations (multiple clients/services lines listed). SearchProviders module currently has no Portuguese logs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:09:54.585Z
Learning: In the MeAjudaAi codebase, when reviewing log messages in application handlers, verify they are in English. The file src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs had Portuguese logs that violated the English-only logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:32:51.210Z
Learning: Além de manter logs em inglês, os comentários e a documentação XML (/// <summary>, <param>, etc.) devem ser escritos em português em todo o código MeAjudaAi.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Locations/API/Endpoints/GetAllowedCityByIdEndpoint.cs:38-38
Timestamp: 2025-12-17T21:10:58.245Z
Learning: In the MeAjudaAi codebase, there are three distinct language standards: (1) Logs must be in English, (2) Comments and XML summaries (///, <summary>, <param>, etc.) must be in Portuguese, (3) User-facing validation messages and API responses shown to the frontend must be in Portuguese. User-facing messages include error responses like Results.NotFound, Results.BadRequest, and constants in ValidationMessages.cs.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 29
File: tests/MeAjudaAi.Shared.Tests/Middleware/GeographicRestrictionMiddlewareTests.cs:178-178
Timestamp: 2025-11-25T01:05:52.410Z
Learning: In the MeAjudaAi codebase, the standard for comments is Portuguese (due to the Brazilian team), and English is only required for logs. Do not suggest changing Portuguese comments to English.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 77
File: src/Modules/Documents/Application/Handlers/UploadDocumentCommandHandler.cs:133-143
Timestamp: 2025-12-17T18:18:43.521Z
Learning: In the MeAjudaAi codebase, Portuguese log messages were found across 9 files: Documents module handlers/ModuleApi/Jobs (35+ logs), Shared Jobs/Seeding/RabbitMq (7 logs), and integration test infrastructure (5 logs). The Documents module is the primary violator with most Portuguese logs requiring translation to English per the logging policy.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-04-07T22:57:34.721Z
Learning: In the MeAjudaAi codebase, when internal classes in src/Shared (e.g., BusinessMetrics, BusinessMetricsMiddleware, MetricsCollectorService) are made public solely for test visibility, the preferred approach is to use `[assembly: InternalsVisibleTo("MeAjudaAi.Shared.Tests")]` in the Shared project instead, keeping the classes `internal`. This preserves encapsulation while allowing test access.
Learnt from: frigini
Repo: frigini/MeAjudaAi PR: 0
File: :0-0
Timestamp: 2026-04-08T01:57:29.285Z
Learning: In the MeAjudaAi codebase, making BusinessMetrics, BusinessMetricsMiddleware, and MetricsCollectorService `public` (instead of `internal`) is the accepted approach when Moq proxy generation fails due to C# 12 primary constructors combined with generic loggers (ILogger<T>). Even with `InternalsVisibleTo("DynamicProxyGenAssembly2")`, Moq cannot reliably generate proxies for primary constructor types. The `public` visibility is justified because these classes are DI-registered infrastructure shared across modules.
Code Coverage Report
|
Minimum allowed line rate is |
Summary
Changes
docs/roadmap.mdanddocs/roadmap-current.mdREADME.mdwith new tech stackdocs/technical-debt.md(removed bUnit/MudBlazor sections)docs/admin-portal/docs for React stackdocs/architecture.mdwith React + PlaywrightSprint 8E Scope
Pre-MVP Priorities
Summary by CodeRabbit
New Features
Documentation
Tests
CI/CD & Infra
Chores